-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
jar-o
committed
Jan 15, 2024
1 parent
41f25a8
commit 69072d8
Showing
6 changed files
with
276 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// SPDX-License-Identifier: AGPL-3.0 | ||
pragma solidity >=0.8.0; | ||
|
||
// https://github.com/marsfoundation/sparklend-advanced/blob/277ea9d9ad7faf330b88198c9c6de979a2fad561/src/interfaces/IRateSource.sol | ||
|
||
interface IRateSource { | ||
function getAPR() external view returns (uint); | ||
} |
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,37 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity ^0.8.16; | ||
|
||
import {IChronicle} from "chronicle-std/IChronicle.sol"; | ||
|
||
import {IRateSource} from "./IRateSource.sol"; | ||
import {Scribe} from "../Scribe.sol"; | ||
|
||
/** | ||
* @title ScribeLST | ||
* | ||
* @notice Schnorr based Oracle with onchain fault resolution for Liquid | ||
* Staking Tokens. | ||
*/ | ||
contract ScribeLST is Scribe, IRateSource { | ||
constructor(address initialAuthed_, bytes32 wat_) | ||
Scribe(initialAuthed_, wat_) | ||
{} | ||
|
||
function getAPR() external view returns (uint) { | ||
uint val = _pokeData.val; | ||
require(val != 0); | ||
return val; | ||
} | ||
} | ||
|
||
/** | ||
* @dev Contract overwrite to deploy contract instances with specific naming. | ||
* | ||
* For more info, see docs/Deployment.md. | ||
*/ | ||
contract Chronicle_BASE_QUOTE_COUNTER is ScribeLST { | ||
// @todo ^^^^ ^^^^^ ^^^^^^^ Adjust name of Scribe instance. | ||
constructor(address initialAuthed, bytes32 wat_) | ||
ScribeLST(initialAuthed, wat_) | ||
{} | ||
} |
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,37 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity ^0.8.16; | ||
|
||
import {IChronicle} from "chronicle-std/IChronicle.sol"; | ||
|
||
import {IRateSource} from "./IRateSource.sol"; | ||
import {ScribeOptimistic} from "../ScribeOptimistic.sol"; | ||
|
||
/** | ||
* @title ScribeOptimisticLST | ||
* | ||
* @notice Schnorr based optimistic Oracle with onchain fault resolution for | ||
* Liquid Staking Tokens. | ||
*/ | ||
contract ScribeOptimisticLST is ScribeOptimistic, IRateSource { | ||
constructor(address initialAuthed_, bytes32 wat_) | ||
ScribeOptimistic(initialAuthed_, wat_) | ||
{} | ||
|
||
function getAPR() external view returns (uint) { | ||
uint val = _currentPokeData().val; | ||
require(val != 0); | ||
return val; | ||
} | ||
} | ||
|
||
/** | ||
* @dev Contract overwrite to deploy contract instances with specific naming. | ||
* | ||
* For more info, see docs/Deployment.md. | ||
*/ | ||
contract Chronicle_BASE_QUOTE_COUNTER is ScribeOptimisticLST { | ||
// @todo ^^^^ ^^^^^ ^^^^^^^ Adjust name of Scribe instance. | ||
constructor(address initialAuthed, bytes32 wat_) | ||
ScribeOptimisticLST(initialAuthed, wat_) | ||
{} | ||
} |
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,88 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.16; | ||
|
||
import {Test} from "forge-std/Test.sol"; | ||
|
||
import {IToll} from "chronicle-std/toll/IToll.sol"; | ||
|
||
import {IScribe} from "src/IScribe.sol"; | ||
import {ScribeOptimisticLST} from "src/extensions/ScribeOptimisticLST.sol"; | ||
|
||
import {LibSecp256k1} from "src/libs/LibSecp256k1.sol"; | ||
|
||
import {LibFeed} from "script/libs/LibFeed.sol"; | ||
|
||
abstract contract IScribeOptimisticTestLST is Test { | ||
using LibFeed for LibFeed.Feed; | ||
using LibFeed for LibFeed.Feed[]; | ||
|
||
ScribeOptimisticLST private scribe; | ||
|
||
bytes32 internal WAT; | ||
bytes32 internal FEED_REGISTRATION_MESSAGE; | ||
|
||
function setUp(address payable scribe_) internal virtual { | ||
scribe = ScribeOptimisticLST(scribe_); | ||
|
||
// Cache constants. | ||
WAT = scribe.wat(); | ||
FEED_REGISTRATION_MESSAGE = scribe.feedRegistrationMessage(); | ||
|
||
// Toll address(this). | ||
IToll(address(scribe)).kiss(address(this)); | ||
} | ||
|
||
function _liftFeeds(uint8 numberFeeds) | ||
internal | ||
returns (LibFeed.Feed[] memory) | ||
{ | ||
LibFeed.Feed[] memory feeds = new LibFeed.Feed[](uint(numberFeeds)); | ||
|
||
// Note to not start with privKey=1. This is because the sum of public | ||
// keys would evaluate to: | ||
// pubKeyOf(1) + pubKeyOf(2) + pubKeyOf(3) + ... | ||
// = pubKeyOf(3) + pubKeyOf(3) + ... | ||
// Note that pubKeyOf(3) would be doubled. Doubling is not supported by | ||
// LibSecp256k1 as this would indicate a double-signing attack. | ||
uint privKey = 2; | ||
uint bloom; | ||
uint ctr; | ||
while (ctr != numberFeeds) { | ||
LibFeed.Feed memory feed = LibFeed.newFeed({privKey: privKey}); | ||
|
||
// Check whether feed with id already created, if not create and | ||
// lift. | ||
if (bloom & (1 << feed.id) == 0) { | ||
bloom |= 1 << feed.id; | ||
|
||
feeds[ctr++] = feed; | ||
scribe.lift( | ||
feed.pubKey, feed.signECDSA(FEED_REGISTRATION_MESSAGE) | ||
); | ||
} | ||
|
||
privKey++; | ||
} | ||
|
||
return feeds; | ||
} | ||
|
||
function test_getAPR() public { | ||
// An actual value, i.e. | ||
// CFG_ETH_RPC_URLS="$ETH_RPC_URL" go1.21.1 run ./cmd/gofer data 'LIDO_LST/7DAYS' | ||
uint val = 3592236075648471881; | ||
|
||
LibFeed.Feed[] memory feeds = _liftFeeds(scribe.bar()); | ||
|
||
IScribe.PokeData memory pokeData; | ||
pokeData.val = uint128(val); | ||
pokeData.age = 1; | ||
|
||
IScribe.SchnorrData memory schnorrData; | ||
schnorrData = feeds.signSchnorr(scribe.constructPokeMessage(pokeData)); | ||
|
||
scribe.poke(pokeData, schnorrData); | ||
assertEq(scribe.getAPR(), val); | ||
assertEq(scribe.getAPR(), scribe.read()); | ||
} | ||
} |
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,88 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.16; | ||
|
||
import {Test} from "forge-std/Test.sol"; | ||
|
||
import {IToll} from "chronicle-std/toll/IToll.sol"; | ||
|
||
import {IScribe} from "src/IScribe.sol"; | ||
import {ScribeLST} from "src/extensions/ScribeLST.sol"; | ||
|
||
import {LibSecp256k1} from "src/libs/LibSecp256k1.sol"; | ||
|
||
import {LibFeed} from "script/libs/LibFeed.sol"; | ||
|
||
abstract contract IScribeTestLST is Test { | ||
using LibFeed for LibFeed.Feed; | ||
using LibFeed for LibFeed.Feed[]; | ||
|
||
ScribeLST private scribe; | ||
|
||
bytes32 internal WAT; | ||
bytes32 internal FEED_REGISTRATION_MESSAGE; | ||
|
||
function setUp(address scribe_) internal virtual { | ||
scribe = ScribeLST(scribe_); | ||
|
||
// Cache constants. | ||
WAT = scribe.wat(); | ||
FEED_REGISTRATION_MESSAGE = scribe.feedRegistrationMessage(); | ||
|
||
// Toll address(this). | ||
IToll(address(scribe)).kiss(address(this)); | ||
} | ||
|
||
function _liftFeeds(uint8 numberFeeds) | ||
internal | ||
returns (LibFeed.Feed[] memory) | ||
{ | ||
LibFeed.Feed[] memory feeds = new LibFeed.Feed[](uint(numberFeeds)); | ||
|
||
// Note to not start with privKey=1. This is because the sum of public | ||
// keys would evaluate to: | ||
// pubKeyOf(1) + pubKeyOf(2) + pubKeyOf(3) + ... | ||
// = pubKeyOf(3) + pubKeyOf(3) + ... | ||
// Note that pubKeyOf(3) would be doubled. Doubling is not supported by | ||
// LibSecp256k1 as this would indicate a double-signing attack. | ||
uint privKey = 2; | ||
uint bloom; | ||
uint ctr; | ||
while (ctr != numberFeeds) { | ||
LibFeed.Feed memory feed = LibFeed.newFeed({privKey: privKey}); | ||
|
||
// Check whether feed with id already created, if not create and | ||
// lift. | ||
if (bloom & (1 << feed.id) == 0) { | ||
bloom |= 1 << feed.id; | ||
|
||
feeds[ctr++] = feed; | ||
scribe.lift( | ||
feed.pubKey, feed.signECDSA(FEED_REGISTRATION_MESSAGE) | ||
); | ||
} | ||
|
||
privKey++; | ||
} | ||
|
||
return feeds; | ||
} | ||
|
||
function test_getAPR() public { | ||
// An actual value, i.e. | ||
// CFG_ETH_RPC_URLS="$ETH_RPC_URL" go1.21.1 run ./cmd/gofer data 'LIDO_LST/1DAY' | ||
uint val = 3386003474307116517; | ||
|
||
LibFeed.Feed[] memory feeds = _liftFeeds(scribe.bar()); | ||
|
||
IScribe.PokeData memory pokeData; | ||
pokeData.val = uint128(val); | ||
pokeData.age = 1; | ||
|
||
IScribe.SchnorrData memory schnorrData; | ||
schnorrData = feeds.signSchnorr(scribe.constructPokeMessage(pokeData)); | ||
|
||
scribe.poke(pokeData, schnorrData); | ||
assertEq(scribe.getAPR(), val); | ||
assertEq(scribe.getAPR(), scribe.read()); | ||
} | ||
} |
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