From 9a801a12c9277a45c41582b837e4cd27fadca8f0 Mon Sep 17 00:00:00 2001 From: Pablo Maldonado Date: Fri, 2 Feb 2024 15:40:18 +0000 Subject: [PATCH] feat: update oval oracle Signed-off-by: Pablo Maldonado --- .gitmodules | 6 --- lib/oev-contracts | 1 - lib/oval-contracts | 1 - remappings.txt | 3 +- script/HoneyPot.s.sol | 50 +++++++++++-------------- src/HoneyPot.sol | 2 +- src/HoneyPotOval.sol | 29 --------------- test/HoneyPot.sol | 85 +++++-------------------------------------- 8 files changed, 33 insertions(+), 144 deletions(-) delete mode 160000 lib/oev-contracts delete mode 160000 lib/oval-contracts delete mode 100644 src/HoneyPotOval.sol diff --git a/.gitmodules b/.gitmodules index 11fd723..7e7b428 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,12 +4,6 @@ [submodule "lib/openzeppelin-contracts"] path = lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts -[submodule "lib/oval-contracts"] - path = lib/oval-contracts - url = https://github.com/UMAprotocol/oval-contracts -[submodule "lib/oev-contracts"] - path = lib/oev-contracts - url = https://github.com/UMAprotocol/oev-contracts [submodule "lib/oval-quickstart"] path = lib/oval-quickstart url = https://github.com/UMAprotocol/oval-quickstart diff --git a/lib/oev-contracts b/lib/oev-contracts deleted file mode 160000 index bd6b77b..0000000 --- a/lib/oev-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bd6b77ba41e4c21a63fce6bdd7e87da34a041379 diff --git a/lib/oval-contracts b/lib/oval-contracts deleted file mode 160000 index 25afc49..0000000 --- a/lib/oval-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 25afc497af220adbc580b9c4ab04ab2485f3a564 diff --git a/remappings.txt b/remappings.txt index e4f5a15..a421151 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,5 +1,4 @@ ds-test/=lib/forge-std/lib/ds-test/src/ forge-std/=lib/forge-std/src/ -oval-contracts/=lib/oval-contracts/src/ -oev-contracts/=lib/oev-contracts/src/ +oval-quickstart/=lib/oval-quickstart/src/ @openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/ \ No newline at end of file diff --git a/script/HoneyPot.s.sol b/script/HoneyPot.s.sol index 9d7bd55..53a63c9 100644 --- a/script/HoneyPot.s.sol +++ b/script/HoneyPot.s.sol @@ -4,45 +4,39 @@ pragma solidity ^0.8.0; import "forge-std/console2.sol"; import "forge-std/Script.sol"; -import {ChronicleMedianSourceMock} from "../src/mock/ChronicleMedianSourceMock.sol"; -import {IMedian} from "oev-contracts/interfaces/chronicle/IMedian.sol"; -import {HoneyPotOval} from "../src/HoneyPotOval.sol"; import {HoneyPot} from "../src/HoneyPot.sol"; import {HoneyPotDAO} from "../src/HoneyPotDAO.sol"; -import {IAggregatorV3Source} from "oval-contracts/interfaces/chainlink/IAggregatorV3Source.sol"; +import {ChainlinkOvalImmutable, IAggregatorV3Source} from "oval-quickstart/ChainlinkOvalImmutable.sol"; contract HoneyPotDeploymentScript is Script { - HoneyPotOval oval; - HoneyPot honeyPot; - HoneyPotDAO honeyPotDAO; - ChronicleMedianSourceMock chronicleMock; - function run() external { - vm.startBroadcast(); + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + address chainlink = vm.envAddress("SOURCE_ADDRESS"); + uint256 lockWindow = vm.envUint("LOCK_WINDOW"); + uint256 maxTraversal = vm.envUint("MAX_TRAVERSAL"); + + // This script assumes exactly one unlocker is set. If you want to set more than one, you'll need to modify this + // script to have an array of known unlocker addresses. + string memory unlockersString = vm.envString("UNLOCKERS"); + address[] memory unlockers = new address[](1); + unlockers[0] = address(uint160(uint256(keccak256(abi.encodePacked(unlockersString))))); + + IAggregatorV3Source source = IAggregatorV3Source(chainlink); + uint8 decimals = IAggregatorV3Source(chainlink).decimals(); + vm.startBroadcast(deployerPrivateKey); - address chainlink = vm.envOr("CHAINLINK_SOURCE", 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419); - address pyth = vm.envOr("PYTH_SOURCE", 0x4305FB66699C3B2702D4d05CF36551390A4c69C6); + ChainlinkOvalImmutable oracle = + new ChainlinkOvalImmutable(source, decimals, lockWindow, maxTraversal, unlockers); - bytes32 defaultId = 0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace; - bytes32 pythPriceId = vm.envOr("PYTH_PRICE_ID", bytes32(0)); - if (pythPriceId == bytes32(0)) { - pythPriceId = defaultId; - } + console.log("Deployed ChainlinkOvalImmutable contract at address: ", address(oracle)); - // Create mock ChronicleMedianSource and set the latest source data. - chronicleMock = new ChronicleMedianSourceMock(); + HoneyPot honeyPot = new HoneyPot(IAggregatorV3Source(address(oracle))); - oval = new HoneyPotOval( - chainlink, - address(chronicleMock), - pyth, - pythPriceId, - 8 - ); + console.log("Deployed HoneyPot contract at address: ", address(honeyPot)); - honeyPot = new HoneyPot(IAggregatorV3Source(address(oval))); + HoneyPotDAO honeyPotDAO = new HoneyPotDAO(); - honeyPotDAO = new HoneyPotDAO(); + console.log("Deployed HoneyPotDAO contract at address: ", address(honeyPotDAO)); vm.stopBroadcast(); } diff --git a/src/HoneyPot.sol b/src/HoneyPot.sol index e868d91..809d77c 100644 --- a/src/HoneyPot.sol +++ b/src/HoneyPot.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.17; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; -import {IAggregatorV3Source} from "oval-contracts/interfaces/chainlink/IAggregatorV3Source.sol"; +import {IAggregatorV3Source} from "oval-quickstart/ChainlinkOvalImmutable.sol"; contract HoneyPot is Ownable { struct HoneyPotDetails { diff --git a/src/HoneyPotOval.sol b/src/HoneyPotOval.sol deleted file mode 100644 index 81feb16..0000000 --- a/src/HoneyPotOval.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0-only -pragma solidity 0.8.17; - -import {BoundedUnionSourceAdapter} from "oev-contracts/adapters/source-adapters/BoundedUnionSourceAdapter.sol"; -import {BaseController} from "oev-contracts/controllers/BaseController.sol"; -import {ChainlinkDestinationAdapter} from "oev-contracts/adapters/destination-adapters/ChainlinkDestinationAdapter.sol"; -import {IAggregatorV3Source} from "oev-contracts/interfaces/chainlink/IAggregatorV3Source.sol"; -import {IMedian} from "oev-contracts/interfaces/chronicle/IMedian.sol"; -import {IPyth} from "oev-contracts/interfaces/pyth/IPyth.sol"; - -contract HoneyPotOval is BaseController, BoundedUnionSourceAdapter, ChainlinkDestinationAdapter { - constructor( - address chainlinkSource, - address chronicleSource, - address pythSource, - bytes32 pythPriceId, - uint8 decimals - ) - BoundedUnionSourceAdapter( - IAggregatorV3Source(chainlinkSource), - IMedian(chronicleSource), - IPyth(pythSource), - pythPriceId, - 0.1e18 - ) - BaseController() - ChainlinkDestinationAdapter(decimals) - {} -} diff --git a/test/HoneyPot.sol b/test/HoneyPot.sol index 820d817..a1cb51e 100644 --- a/test/HoneyPot.sol +++ b/test/HoneyPot.sol @@ -2,14 +2,9 @@ pragma solidity 0.8.17; import {CommonTest} from "./Common.sol"; -import {IAggregatorV3Source} from "oval-contracts/interfaces/chainlink/IAggregatorV3Source.sol"; -import {IMedian} from "oev-contracts/interfaces/chronicle/IMedian.sol"; -import {IPyth} from "oev-contracts/interfaces/pyth/IPyth.sol"; - -import {HoneyPotOval} from "../src/HoneyPotOval.sol"; import {HoneyPot} from "../src/HoneyPot.sol"; import {HoneyPotDAO} from "../src/HoneyPotDAO.sol"; -import {ChronicleMedianSourceMock} from "../src/mock/ChronicleMedianSourceMock.sol"; +import {ChainlinkOvalImmutable, IAggregatorV3Source} from "oval-quickstart/ChainlinkOvalImmutable.sol"; contract HoneyPotTest is CommonTest { event ReceivedEther(address sender, uint256 amount); @@ -20,13 +15,7 @@ contract HoneyPotTest is CommonTest { event PotReset(address indexed owner, uint256 amount); IAggregatorV3Source chainlink = IAggregatorV3Source(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419); - IMedian chronicle = IMedian(0x64DE91F5A373Cd4c28de3600cB34C7C6cE410C85); - IPyth pyth = IPyth(0x4305FB66699C3B2702D4d05CF36551390A4c69C6); - bytes32 pythPriceId = 0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace; - - ChronicleMedianSourceMock chronicleMock; - - HoneyPotOval oval; + ChainlinkOvalImmutable oracle; HoneyPot honeyPot; HoneyPotDAO honeyPotDAO; @@ -35,30 +24,17 @@ contract HoneyPotTest is CommonTest { function setUp() public { vm.createSelectFork("mainnet", 18419040); // Recent block on mainnet - oval = new HoneyPotOval( - address(chainlink), - address(chronicle), - address(pyth), - pythPriceId, - 8 - ); + address[] memory unlockers = new address[](1); + unlockers[0] = address(this); + uint8 decimals = chainlink.decimals(); + oracle = new ChainlinkOvalImmutable(chainlink, decimals, 3, 10, unlockers); - honeyPot = new HoneyPot(IAggregatorV3Source(address(oval))); + honeyPot = new HoneyPot(IAggregatorV3Source(address(oracle))); honeyPotDAO = new HoneyPotDAO(); - _whitelistOnChronicle(); - oval.setUnlocker(address(this), true); - chronicleMock = new ChronicleMedianSourceMock(); } receive() external payable {} - function _whitelistOnChronicle() internal { - vm.startPrank(0xBE8E3e3618f7474F8cB1d074A26afFef007E98FB); // DSPause that is a ward (can add kiss to chronicle) - chronicle.kiss(address(oval)); - chronicle.kiss(address(this)); // So that we can read Chronicle directly. - vm.stopPrank(); - } - function mockChainlinkPriceChange() public { (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) = chainlink.latestRoundData(); @@ -96,7 +72,7 @@ contract HoneyPotTest is CommonTest { function testCrackHoneyPot() public { // Create HoneyPot for the caller - (, int256 currentPrice,,,) = oval.latestRoundData(); + (, int256 currentPrice,,,) = oracle.latestRoundData(); vm.expectEmit(true, true, true, true); emit HoneyPotCreated(address(this), currentPrice, honeyPotBalance); honeyPot.createHoneyPot{value: honeyPotBalance}(); @@ -111,7 +87,7 @@ contract HoneyPotTest is CommonTest { mockChainlinkPriceChange(); // Unlock the latest value - oval.unlockLatestValue(); + oracle.unlockLatestValue(); uint256 liquidatorBalanceBefore = liquidator.balance; @@ -140,49 +116,6 @@ contract HoneyPotTest is CommonTest { honeyPotDAO.drain(); } - function testChronicleMock() public { - uint32 age = chronicle.age(); - uint256 read = chronicle.read(); - chronicleMock.setLatestSourceData(read, age); - - HoneyPotOval oval2 = new HoneyPotOval( - address(chainlink), - address(chronicleMock), - address(pyth), - pythPriceId, - 8 - ); - oval2.setUnlocker(address(this), true); - - HoneyPot honeyPot2 = new HoneyPot( - IAggregatorV3Source(address(oval2)) - ); - - // Create HoneyPot for the caller - honeyPot2.createHoneyPot{value: honeyPotBalance}(); - (, uint256 testhoneyPotBalance) = honeyPot2.honeyPots(address(this)); - assertTrue(testhoneyPotBalance == honeyPotBalance); - - vm.prank(liquidator); - vm.expectRevert("Liquidation price reached for this user"); - honeyPot2.emptyHoneyPot(address(this)); - - // Simulate price change - chronicleMock.setLatestSourceData((read * 103) / 100, uint32(block.timestamp - 1)); - - // Unlock the latest value - oval2.unlockLatestValue(); - - uint256 liquidatorBalanceBefore = liquidator.balance; - - vm.prank(liquidator); - honeyPot2.emptyHoneyPot(address(this)); - - uint256 liquidatorBalanceAfter = liquidator.balance; - - assertTrue(liquidatorBalanceAfter == liquidatorBalanceBefore + honeyPotBalance); - } - function testCreateHoneyPotWithNoValue() public { vm.expectRevert("No value sent"); honeyPot.createHoneyPot{value: 0}();