Skip to content

Commit

Permalink
feat: explicit rounding in getClaimPreview function (#3)
Browse files Browse the repository at this point in the history
* feat: update `getClaimPreview` function
The `getClaimPreview` function was updated by adding `bool round` parameter for explicit rounding mode.
* chore: update `hardhat.config.ts`
* feat: update contract version to `v2.1.0`
* style: contract formatting
* style: `hardhat.config.ts` formatting
* docs: remove the note about rounding for the ClaimPreview structure
---------
Co-authored-by: Evgenii Zaitsev <[email protected]>
  • Loading branch information
igorsenych-cw authored Nov 21, 2024
1 parent b2c9bed commit 2e2fe82
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 64 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ OPTIMIZER_ENABLED = true
OPTIMIZER_RUNS = 1000
GAS_REPORTER_ENABLED = false
CONTRACT_SIZER_ENABLED = false
ALLOW_UNLIMITED_CONTRACT_SIZE = false
ALLOW_UNLIMITED_CONTRACT_SIZE = true
HARDHAT_MNEMONIC = test test test test test test test test test test test junk
GANACHE_RPC = http://127.0.0.1:7545
GANACHE_MNEMONIC = test test test test test test test test test test test junk
Expand Down
4 changes: 2 additions & 2 deletions contracts/YieldStreamer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ contract YieldStreamer is
/**
* @inheritdoc IYieldStreamerPrimary_Functions
*/
function getClaimPreview(address account) external view returns (ClaimPreview memory) {
return _getClaimPreview(account, _blockTimestamp());
function getClaimPreview(address account, bool round) external view returns (ClaimPreview memory) {
return _getClaimPreview(account, _blockTimestamp(), round);
}

/**
Expand Down
9 changes: 5 additions & 4 deletions contracts/YieldStreamerPrimary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,11 @@ abstract contract YieldStreamerPrimary is
* @param account The account to get the claim preview for.
* @return A `ClaimPreview` struct containing details of the claimable yield.
*/
function _getClaimPreview(address account, uint256 currentTimestamp) internal view returns (ClaimPreview memory) {
function _getClaimPreview(address account, uint256 currentTimestamp, bool round) internal view returns (ClaimPreview memory) {
YieldStreamerStorageLayout storage $ = _yieldStreamerStorage();
YieldState storage state = $.yieldStates[account];
YieldRate[] storage rates = $.yieldRates[$.groups[account].id];
return _map(_getAccruePreview(state, rates, currentTimestamp));
return _map(_getAccruePreview(state, rates, currentTimestamp), round);
}

/**
Expand Down Expand Up @@ -1031,11 +1031,12 @@ abstract contract YieldStreamerPrimary is
* @dev Maps an `AccruePreview` struct to a `ClaimPreview` struct.
*
* @param accruePreview The `AccruePreview` struct to map from.
* @param round Whether to round the yield and fee amounts.
* @return claimPreview The resulting `ClaimPreview` struct.
*/
function _map(AccruePreview memory accruePreview) internal pure returns (ClaimPreview memory claimPreview) {
function _map(AccruePreview memory accruePreview, bool round) internal pure returns (ClaimPreview memory claimPreview) {
uint256 totalYield = accruePreview.accruedYieldAfter + accruePreview.streamYieldAfter;
claimPreview.yield = _roundDown(totalYield);
claimPreview.yield = round ? _roundDown(totalYield) : totalYield;
claimPreview.fee = 0; // Fees are not supported yet.
claimPreview.timestamp = accruePreview.toTimestamp;
claimPreview.balance = accruePreview.balance;
Expand Down
2 changes: 1 addition & 1 deletion contracts/base/Versionable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ abstract contract Versionable is IVersionable {
* @inheritdoc IVersionable
*/
function $__VERSION() external pure returns (Version memory) {
return Version(2, 0, 0);
return Version(2, 1, 0);
}
}
6 changes: 5 additions & 1 deletion contracts/interfaces/IYieldStreamerPrimary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,13 @@ interface IYieldStreamerPrimary_Functions {
* Estimates the yield amount that can be claimed without modifying the contract state.
*
* @param account The address of the account to query.
* @param round Whether to round the yield and fee amounts.
* @return A `ClaimPreview` struct containing details of the claimable yield.
*/
function getClaimPreview(address account) external view returns (IYieldStreamerTypes.ClaimPreview memory);
function getClaimPreview(
address account,
bool round
) external view returns (IYieldStreamerTypes.ClaimPreview memory);

/**
* @dev Provides a preview of the yield accrual for a given account over time.
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IYieldStreamerTypes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ interface IYieldStreamerTypes {
* Used to estimate the yield that can be claimed without modifying the contract state.
*
* Fields:
* - `yield`: The total claimable yield amount (rounded down) available for the account.
* - `yield`: The total claimable yield amount available for the account.
* - `fee`: The fee amount that would be deducted during the claim.
* - `timestamp`: The timestamp at which the preview was calculated.
* - `balance`: The account's token balance used in the calculation.
Expand Down
4 changes: 2 additions & 2 deletions contracts/testable/YieldStreamerTestable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ contract YieldStreamerTestable is YieldStreamer {
return _roundUp(amount);
}

function map(AccruePreview memory accrue) external pure returns (ClaimPreview memory) {
return _map(accrue);
function map(AccruePreview memory accrue, bool round) external pure returns (ClaimPreview memory) {
return _map(accrue, round);
}
}
5 changes: 1 addition & 4 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ const config: HardhatUserConfig = {
accounts: {
mnemonic: process.env.HARDHAT_MNEMONIC
},
allowUnlimitedContractSize:
process.env.ALLOW_UNLIMITED_CONTRACT_SIZE !== undefined
? process.env.ALLOW_UNLIMITED_CONTRACT_SIZE === "true"
: true
allowUnlimitedContractSize: process.env.ALLOW_UNLIMITED_CONTRACT_SIZE === "true"
},
ganache: {
url: process.env.GANACHE_RPC,
Expand Down
2 changes: 1 addition & 1 deletion test/YieldStreamer.schedule.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ describe("YieldStreamer - Deposit/Withdraw Simulation Tests", function () {
let adjustedBlockTime: number;
const EXPECTED_VERSION: Version = {
major: 2,
minor: 0,
minor: 1,
patch: 0
};

Expand Down
2 changes: 1 addition & 1 deletion test/YieldStreamerHarness.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ describe("YieldStreamerHarness", function () {
const harnessAdminRole: string = ethers.id("HARNESS_ADMIN_ROLE");
const EXPECTED_VERSION: Version = {
major: 2,
minor: 0,
minor: 1,
patch: 0
};

Expand Down
123 changes: 77 additions & 46 deletions test/YieldStreamerTestable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2290,60 +2290,88 @@ describe("YieldStreamerTestable", async () => {
});

describe("Function 'map()'", async () => {
it("Should map as expected", async () => {
// Create an `AccruePreview` struct with sample data
const accruePreview: AccruePreview = {
fromTimestamp: 10000000n,
toTimestamp: 20000000n,
balance: 30000000n,
streamYieldBefore: 199996n,
accruedYieldBefore: 299996n,
streamYieldAfter: 499996n,
accruedYieldAfter: 399996n,
rates: [
{
tiers: [
{ rate: 101n, cap: 102n },
{ rate: 201n, cap: 202n }
],
effectiveDay: 1n
},
{
tiers: [
{ rate: 301n, cap: 302n },
{ rate: 401n, cap: 402n }
],
effectiveDay: 9n
}
],
results: [
{
partialFirstDayYield: 111n,
fullDaysYield: 211n,
partialLastDayYield: 311n,
partialFirstDayYieldTiered: [101n, 10n],
fullDaysYieldTiered: [201n, 10n],
partialLastDayYieldTiered: [301n, 10n]
},
{
partialFirstDayYield: 411n,
fullDaysYield: 511n,
partialLastDayYield: 611n,
partialFirstDayYieldTiered: [401n, 10n],
fullDaysYieldTiered: [501n, 10n],
partialLastDayYieldTiered: [601n, 10n]
}
]
};

it("Should map as expected (rounded)", async () => {
const { yieldStreamerTestable } = await setUpFixture(deployContracts);

// Create an `AccruePreview` struct with sample data
const accruePreview: AccruePreview = {
fromTimestamp: 10000000n,
toTimestamp: 20000000n,
balance: 30000000n,
streamYieldBefore: 199996n,
accruedYieldBefore: 299996n,
streamYieldAfter: 499996n,
accruedYieldAfter: 399996n,
rates: [
{
tiers: [
{ rate: 101n, cap: 102n },
{ rate: 201n, cap: 202n }
],
effectiveDay: 1n
},
{
tiers: [
{ rate: 301n, cap: 302n },
{ rate: 401n, cap: 402n }
],
effectiveDay: 9n
}
],
results: [
{
partialFirstDayYield: 111n,
fullDaysYield: 211n,
partialLastDayYield: 311n,
partialFirstDayYieldTiered: [101n, 10n],
fullDaysYieldTiered: [201n, 10n],
partialLastDayYieldTiered: [301n, 10n]
},
{
partialFirstDayYield: 411n,
fullDaysYield: 511n,
partialLastDayYield: 611n,
partialFirstDayYieldTiered: [401n, 10n],
fullDaysYieldTiered: [501n, 10n],
partialLastDayYieldTiered: [601n, 10n]
}
]
// Call the `map` function
const claimPreviewRaw: ClaimPreview = await yieldStreamerTestable.map(accruePreview, true);

// Create the `ClaimPreview` struct with expected values
const expectedClaimPreview: ClaimPreview = {
yield: roundDown(accruePreview.accruedYieldAfter + accruePreview.streamYieldAfter),
balance: accruePreview.balance,
fee: 0n,
timestamp: accruePreview.toTimestamp,
rates: accruePreview.rates[accruePreview.rates.length - 1].tiers.map(tier => tier.rate),
caps: accruePreview.rates[accruePreview.rates.length - 1].tiers.map(tier => tier.cap)
};

// Assertion
expect(accruePreview.accruedYieldAfter + accruePreview.streamYieldAfter).not.to.equal(
roundDown(accruePreview.accruedYieldAfter + accruePreview.streamYieldAfter)
);
expect(expectedClaimPreview.yield).to.equal(claimPreviewRaw.yield);
expect(expectedClaimPreview.fee).to.equal(claimPreviewRaw.fee);
expect(expectedClaimPreview.timestamp).to.equal(claimPreviewRaw.timestamp);
expect(expectedClaimPreview.balance).to.equal(claimPreviewRaw.balance);
expect(expectedClaimPreview.rates).to.deep.equal(claimPreviewRaw.rates);
expect(expectedClaimPreview.caps).to.deep.equal(claimPreviewRaw.caps);
});

it("Should map as expected (not rounded)", async () => {
const { yieldStreamerTestable } = await setUpFixture(deployContracts);

// Call the `map` function
const claimPreviewRaw: ClaimPreview = await yieldStreamerTestable.map(accruePreview);
const claimPreviewRaw: ClaimPreview = await yieldStreamerTestable.map(accruePreview, false);

// Create the `ClaimPreview` struct with expected values
const expectedClaimPreview: ClaimPreview = {
yield: roundDown(accruePreview.accruedYieldAfter + accruePreview.streamYieldAfter),
yield: accruePreview.accruedYieldAfter + accruePreview.streamYieldAfter,
balance: accruePreview.balance,
fee: 0n,
timestamp: accruePreview.toTimestamp,
Expand All @@ -2352,6 +2380,9 @@ describe("YieldStreamerTestable", async () => {
};

// Assertion
expect(accruePreview.accruedYieldAfter + accruePreview.streamYieldAfter).not.to.equal(
roundDown(accruePreview.accruedYieldAfter + accruePreview.streamYieldAfter)
);
expect(expectedClaimPreview.yield).to.equal(claimPreviewRaw.yield);
expect(expectedClaimPreview.fee).to.equal(claimPreviewRaw.fee);
expect(expectedClaimPreview.timestamp).to.equal(claimPreviewRaw.timestamp);
Expand Down

0 comments on commit 2e2fe82

Please sign in to comment.