-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Matt Rice <[email protected]>
- Loading branch information
Showing
7 changed files
with
212 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.17; | ||
|
||
import {Ownable} from "openzeppelin-contracts/contracts/access/Ownable.sol"; | ||
import {MutableUnlockersController} from "../controllers/MutableUnlockersController.sol"; | ||
import {ChronicleMedianSourceAdapter} from "../adapters/source-adapters/ChronicleMedianSourceAdapter.sol"; | ||
import {ChainlinkDestinationAdapter} from "../adapters/destination-adapters/ChainlinkDestinationAdapter.sol"; | ||
import {IAggregatorV3Source} from "../interfaces/chainlink/IAggregatorV3Source.sol"; | ||
import {BaseFactory} from "./BaseFactory.sol"; | ||
import {IMedian} from "../interfaces/chronicle/IMedian.sol"; | ||
|
||
/** | ||
* @title OvalChronicle is the reccomended Oval contract that allows Oval to extract OEV generated by | ||
* Chronicle price feeds and allow usage via the Chainlink interface. | ||
*/ | ||
contract OvalChronicle is MutableUnlockersController, ChronicleMedianSourceAdapter, ChainlinkDestinationAdapter { | ||
constructor(IMedian source, address[] memory unlockers, uint256 lockWindow, uint256 maxTraversal, address owner) | ||
ChronicleMedianSourceAdapter(source) | ||
MutableUnlockersController(lockWindow, maxTraversal, unlockers) | ||
ChainlinkDestinationAdapter(18) | ||
{ | ||
_transferOwnership(owner); | ||
} | ||
} | ||
|
||
/** | ||
* @title StandardPythFactory is the recommended factory for use cases that want a Chronicle source and Chainlink | ||
* interface. | ||
* @dev This is the best factory for most use cases that need a Chronicle source, but there are other variants that may be | ||
* needed if different mutability or interface choices are desired. | ||
*/ | ||
contract StandardChronicleFactory is Ownable, BaseFactory { | ||
constructor(uint256 maxTraversal, address[] memory _defaultUnlockers) BaseFactory(maxTraversal, _defaultUnlockers) {} | ||
|
||
/** | ||
* @notice Creates the Pyth Oval instance. | ||
* @param chronicle Chronicle source contract. | ||
* @param lockWindow the lockWindow used for this Oval instance. This is the length of the window | ||
* for the Oval auction to be run and, thus, the maximum time that prices will be delayed. | ||
* @return oval deployed oval address. | ||
*/ | ||
function create(IMedian chronicle, uint256 lockWindow) external returns (address oval) { | ||
oval = address(new OvalChronicle(chronicle, defaultUnlockers, lockWindow, MAX_TRAVERSAL, owner())); | ||
emit OvalDeployed(msg.sender, oval, lockWindow, MAX_TRAVERSAL, owner(), defaultUnlockers); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,50 @@ | ||
// // SPDX-License-Identifier: BUSL-1.1 | ||
// pragma solidity 0.8.17; | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.17; | ||
|
||
// import {Ownable} from "openzeppelin-contracts/contracts/access/Ownable.sol"; | ||
// import {MutableUnlockersController} from "../controllers/MutableUnlockersController.sol"; | ||
// import {PythSourceAdapter} from "../adapters/source-adapters/PythSourceAdapter.sol"; | ||
// import {ChainlinkDestinationAdapter} from "../adapters/destination-adapters/ChainlinkDestinationAdapter.sol"; | ||
// import {IAggregatorV3Source} from "../interfaces/chainlink/IAggregatorV3Source.sol"; | ||
// import {BaseFactory} from "./BaseFactory.sol"; | ||
import {Ownable} from "openzeppelin-contracts/contracts/access/Ownable.sol"; | ||
import {MutableUnlockersController} from "../controllers/MutableUnlockersController.sol"; | ||
import {PythSourceAdapter} from "../adapters/source-adapters/PythSourceAdapter.sol"; | ||
import {ChainlinkDestinationAdapter} from "../adapters/destination-adapters/ChainlinkDestinationAdapter.sol"; | ||
import {IAggregatorV3Source} from "../interfaces/chainlink/IAggregatorV3Source.sol"; | ||
import {BaseFactory} from "./BaseFactory.sol"; | ||
import {IPyth} from "../interfaces/pyth/IPyth.sol"; | ||
|
||
// /** | ||
// * @title OvalPyth is the reccomended Oval contract that allows Oval to extract OEV generated by | ||
// * Pyth price feeds and allow usage via the Chainlink interface. | ||
// */ | ||
// contract OvalPyth is MutableUnlockersController, PythSourceAdapter, ChainlinkDestinationAdapter { | ||
// constructor(IAggregatorV3Source source, address[] memory unlockers, uint256 _lockWindow, uint256 _maxTraversal, address owner) | ||
// PythSourceAdapter(source) | ||
// MutableUnlockersController(_lockWindow, _maxTraversal, unlockers) | ||
// ChainlinkDestinationAdapter(source.decimals()) | ||
// { | ||
// _transferOwnership(owner); | ||
// } | ||
// } | ||
/** | ||
* @title OvalPyth is the reccomended Oval contract that allows Oval to extract OEV generated by | ||
* Pyth price feeds and allow usage via the Chainlink interface. | ||
*/ | ||
contract OvalPyth is MutableUnlockersController, PythSourceAdapter, ChainlinkDestinationAdapter { | ||
constructor(IPyth source, bytes32 pythPriceId, address[] memory unlockers, uint256 lockWindow, uint256 maxTraversal, address owner) | ||
PythSourceAdapter(source, pythPriceId) | ||
MutableUnlockersController(lockWindow, maxTraversal, unlockers) | ||
ChainlinkDestinationAdapter(18) | ||
{ | ||
_transferOwnership(owner); | ||
} | ||
} | ||
|
||
// /** | ||
// * @title StandardChainlinkFactory is the reccomended factory for Chainlink source/destination contracts that allow | ||
// * Oval to extract OEV generated by Chainlink usage. | ||
// */ | ||
// contract StandardChainlinkFactory is Ownable { | ||
// /** | ||
// * @notice Creates the Chainlink Oval instance. | ||
// * @param source the Chainlink oracle source contract. | ||
// * @param lockWindow the lockWindow used for this Oval instance. This is the length of the window | ||
// * for the Oval auction to be run and, thus, the maximum time that prices will be delayed. | ||
// */ | ||
// function create(IAggregatorV3Source source, uint256 lockWindow) external returns (address) { | ||
// return address(new OvalChainlink(source, defaultUnlockers, lockWindow, MAX_TRAVERSAL, owner())); | ||
// } | ||
// } | ||
/** | ||
* @title StandardPythFactory is the recommended factory for use cases that want a Pyth source and Chainlink | ||
* interface. | ||
* @dev This is the best factory for most use cases that need a Pyth source, but there are other variants that may be | ||
* needed if different mutability or interface choices are desired. | ||
*/ | ||
contract StandardPythFactory is Ownable, BaseFactory { | ||
IPyth immutable pyth; | ||
|
||
constructor(IPyth _pyth, uint256 maxTraversal, address[] memory _defaultUnlockers) BaseFactory(maxTraversal, _defaultUnlockers) { | ||
pyth = _pyth; | ||
} | ||
|
||
/** | ||
* @notice Creates the Pyth Oval instance. | ||
* @param pythPriceId the Pyth price id. | ||
* @param lockWindow the lockWindow used for this Oval instance. This is the length of the window | ||
* for the Oval auction to be run and, thus, the maximum time that prices will be delayed. | ||
* @return oval deployed oval address. | ||
*/ | ||
function create(bytes32 pythPriceId, uint256 lockWindow) external returns (address oval) { | ||
oval = address(new OvalPyth(pyth, pythPriceId, defaultUnlockers, lockWindow, MAX_TRAVERSAL, owner())); | ||
emit OvalDeployed(msg.sender, oval, lockWindow, MAX_TRAVERSAL, owner(), defaultUnlockers); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.17; | ||
|
||
import {StandardChronicleFactory} from "../../src/factories/StandardChronicleFactory.sol"; | ||
import {OvalChronicle} from "../../src/factories/StandardChronicleFactory.sol"; | ||
import {IMedian} from "../../src/interfaces/chronicle/IMedian.sol"; | ||
import {CommonTest} from "../Common.sol"; | ||
|
||
contract StandardChronicleFactoryTest is CommonTest { | ||
StandardChronicleFactory factory; | ||
IMedian mockSource; | ||
address[] unlockers; | ||
uint256 lockWindow = 300; | ||
uint256 maxTraversal = 15; | ||
|
||
function setUp() public { | ||
mockSource = IMedian(address(0x456)); | ||
unlockers.push(address(0x123)); | ||
factory = new StandardChronicleFactory(maxTraversal, unlockers); | ||
} | ||
|
||
function testCreateMutableUnlockerOvalChronicle() public { | ||
address created = factory.create( | ||
mockSource, lockWindow | ||
); | ||
|
||
assertTrue(created != address(0)); // Check if the address is set, non-zero. | ||
|
||
OvalChronicle instance = OvalChronicle(created); | ||
assertTrue(instance.lockWindow() == lockWindow); | ||
assertTrue(instance.maxTraversal() == maxTraversal); | ||
|
||
// Check if the unlockers are set correctly | ||
for (uint256 i = 0; i < unlockers.length; i++) { | ||
assertTrue(instance.canUnlock(unlockers[i], 0)); | ||
} | ||
assertFalse(instance.canUnlock(address(0x456), 0)); // Check if a random address cannot unlock | ||
} | ||
|
||
function testOwnerCanChangeUnlockers() public { | ||
address created = factory.create( | ||
mockSource, lockWindow | ||
); | ||
OvalChronicle instance = OvalChronicle(created); | ||
|
||
address newUnlocker = address(0x789); | ||
instance.setUnlocker(newUnlocker, true); // Correct method to add unlockers | ||
assertTrue(instance.canUnlock(newUnlocker, 0)); | ||
|
||
instance.setUnlocker(address(0x123), false); // Correct method to remove unlockers | ||
assertFalse(instance.canUnlock(address(0x123), 0)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.17; | ||
|
||
import {StandardPythFactory} from "../../src/factories/StandardPythFactory.sol"; | ||
import {OvalPyth} from "../../src/factories/StandardPythFactory.sol"; | ||
import {IPyth} from "../../src/interfaces/pyth/IPyth.sol"; | ||
import {CommonTest} from "../Common.sol"; | ||
|
||
contract StandardPythFactoryTest is CommonTest { | ||
StandardPythFactory factory; | ||
IPyth mockSource; | ||
address[] unlockers; | ||
uint256 lockWindow = 300; | ||
uint256 maxTraversal = 15; | ||
|
||
function setUp() public { | ||
mockSource = IPyth(address(0x456)); | ||
unlockers.push(address(0x123)); | ||
factory = new StandardPythFactory(mockSource, maxTraversal, unlockers); | ||
} | ||
|
||
function testCreateMutableUnlockerOvalPyth() public { | ||
address created = factory.create( | ||
bytes32(uint256(0x789)), lockWindow | ||
); | ||
|
||
assertTrue(created != address(0)); // Check if the address is set, non-zero. | ||
|
||
OvalPyth instance = OvalPyth(created); | ||
assertTrue(instance.lockWindow() == lockWindow); | ||
assertTrue(instance.maxTraversal() == maxTraversal); | ||
|
||
// Check if the unlockers are set correctly | ||
for (uint256 i = 0; i < unlockers.length; i++) { | ||
assertTrue(instance.canUnlock(unlockers[i], 0)); | ||
} | ||
assertFalse(instance.canUnlock(address(0x456), 0)); // Check if a random address cannot unlock | ||
} | ||
|
||
function testOwnerCanChangeUnlockers() public { | ||
address created = factory.create( | ||
bytes32(uint256(0x789)), lockWindow | ||
); | ||
OvalPyth instance = OvalPyth(created); | ||
|
||
address newUnlocker = address(0x789); | ||
instance.setUnlocker(newUnlocker, true); // Correct method to add unlockers | ||
assertTrue(instance.canUnlock(newUnlocker, 0)); | ||
|
||
instance.setUnlocker(address(0x123), false); // Correct method to remove unlockers | ||
assertFalse(instance.canUnlock(address(0x123), 0)); | ||
} | ||
} |