Skip to content

Commit

Permalink
Merge pull request #114 from eonian-core/fix/subgraph-apy-calculations
Browse files Browse the repository at this point in the history
fix apy calculations in subgraph
  • Loading branch information
LeoVS09 authored Jul 1, 2023
2 parents 5e7c9a7 + fe71f1d commit c8e2c54
Show file tree
Hide file tree
Showing 11 changed files with 40 additions and 36 deletions.
2 changes: 1 addition & 1 deletion packages/contracts/src/strategies/ApeLendingStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ contract ApeLendingStrategy is SafeUUPSUpgradeable, CTokenBaseStrategy {

/// @inheritdoc IVersionable
function version() external pure override returns (string memory) {
return "0.3.1";
return "0.3.2";
}

// ------------------------------------------ Constructors ------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts/src/strategies/CTokenBaseStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ abstract contract CTokenBaseStrategy is ICInterestRate, BaseStrategy {
}

// in this case "PerBlock" actually means "PerSecond"
return cToken.borrowRatePerBlock() / secondPerBlock;
return cToken.borrowRatePerBlock() * secondPerBlock;
}

/// @inheritdoc ICInterestRate
Expand All @@ -116,7 +116,7 @@ abstract contract CTokenBaseStrategy is ICInterestRate, BaseStrategy {
}

// in this case "PerBlock" actually means "PerSecond"
return cToken.supplyRatePerBlock() / secondPerBlock;
return cToken.supplyRatePerBlock() * secondPerBlock;
}

/// @inheritdoc ICInterestRate
Expand Down
15 changes: 9 additions & 6 deletions packages/contracts/test/unit/CTokenBaseStrategy.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -207,45 +207,48 @@ contract CTokenBaseStrategyTest is TestWithERC1820Registry {
// test interestRatePerBlock
function testShouldReturnCorrectInterestRatePerBlock(
bool _blocksBased,
uint256 interestRatePerBlock
uint128 _interestRatePerBlock
) public {
uint256 interestRatePerBlock = _interestRatePerBlock;
cToken.setBlocksBased(_blocksBased);
cToken.setSupplyRatePerBlock(interestRatePerBlock);

if (_blocksBased) {
assertEq(strategy.interestRatePerBlock(), interestRatePerBlock);
} else {
assertEq(strategy.interestRatePerBlock(), interestRatePerBlock / strategy.secondPerBlock());
assertEq(strategy.interestRatePerBlock(), interestRatePerBlock * strategy.secondPerBlock());
}
}

// test borrowRatePerBlock
function testShouldReturnCorrectBorrowRatePerBlock(
bool _blocksBased,
uint256 borrowRatePerBlock
uint128 _borrowRatePerBlock
) public {
uint256 borrowRatePerBlock = _borrowRatePerBlock;
cToken.setBlocksBased(_blocksBased);
cToken.setBorrowRatePerBlock(borrowRatePerBlock);

if (_blocksBased) {
assertEq(strategy.borrowRatePerBlock(), borrowRatePerBlock);
} else {
assertEq(strategy.borrowRatePerBlock(), borrowRatePerBlock / strategy.secondPerBlock());
assertEq(strategy.borrowRatePerBlock(), borrowRatePerBlock * strategy.secondPerBlock());
}
}

// test supplyRatePerBlock
function testShouldReturnCorrectSupplyRatePerBlock(
bool _blocksBased,
uint256 supplyRatePerBlock
uint128 _supplyRatePerBlock
) public {
uint256 supplyRatePerBlock = _supplyRatePerBlock;
cToken.setBlocksBased(_blocksBased);
cToken.setSupplyRatePerBlock(supplyRatePerBlock);

if (_blocksBased) {
assertEq(strategy.supplyRatePerBlock(), supplyRatePerBlock);
} else {
assertEq(strategy.supplyRatePerBlock(), supplyRatePerBlock / strategy.secondPerBlock());
assertEq(strategy.supplyRatePerBlock(), supplyRatePerBlock * strategy.secondPerBlock());
}
}

Expand Down
8 changes: 4 additions & 4 deletions packages/subgraph/generated/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -498,17 +498,17 @@ export class RewardAPY extends Entity {
this.set("decimals", Value.fromI32(value));
}

get dayly(): BigInt {
let value = this.get("dayly");
get daily(): BigInt {
let value = this.get("daily");
if (!value || value.kind == ValueKind.NULL) {
throw new Error("Cannot return null for a required field.");
} else {
return value.toBigInt();
}
}

set dayly(value: BigInt) {
this.set("dayly", Value.fromBigInt(value));
set daily(value: BigInt) {
this.set("daily", Value.fromBigInt(value));
}

get weekly(): BigInt {
Expand Down
2 changes: 1 addition & 1 deletion packages/subgraph/nodemon.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"watch": ["src", "tests"],
"ext": "ts",
"exec": "yarn test"
"exec": "yarn test:local"
}

3 changes: 2 additions & 1 deletion packages/subgraph/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@eonian/subgraph",
"version": "0.9.4",
"version": "0.9.5",
"scripts": {
"gen:code": "graph codegen ./deploy/environments/eonian-sepolia-testnet.yaml",
"dev": "graph codegen ./deploy/environments/eonian-sepolia-testnet.yaml --watch",
Expand All @@ -14,6 +14,7 @@
"deploy:local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 eonian-sepolia-testnet",
"copy:local-schema": "cp ./deploy/environments/local.yaml ./subgraph.yaml",
"test": "graph test",
"test:local": "yarn copy:local-schema && yarn test",
"test:docker": "graph test -d",
"test:watch": "nodemon",
"gen:configs": "node bin/generate-yaml-configs.js ./deploy ./deploy/environments"
Expand Down
2 changes: 1 addition & 1 deletion packages/subgraph/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ type RewardAPY @entity(immutable: false) @regularPolling {
decimals: Int!

" Dayly interest rate, represented as percentage scaled by 10^decimals "
dayly: BigInt!
daily: BigInt!

" Weekly interest rate, represented as percentage scaled by 10^decimals "
weekly: BigInt!
Expand Down
9 changes: 5 additions & 4 deletions packages/subgraph/src/apy/apy-calculations.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Address, Bytes, ethereum, BigInt } from "@graphprotocol/graph-ts";

export const MAX_BPS = 10_000;
export const MAX_BPS = 4;
export const INTEREST_RATE_DECIMALS = 18;
export const PERCENTS_SCALE = BigInt.fromI64(100);

// TODO: add values per chain
Expand All @@ -10,9 +11,9 @@ export const BLOCK_TIME = 3.01; // In seconds, https://ycharts.com/indicators/bi

export const SECONDS_PER_DAY: f64 = 60 * 60 * 24;

export const BLOCKS_PER_WEEK = BigInt.fromI64(Math.round((7 as f64) * SECONDS_PER_DAY * BLOCK_TIME) as i64);
export const BLOCKS_PER_MONTH = BigInt.fromI64(Math.round((30 as f64) * SECONDS_PER_DAY * BLOCK_TIME) as i64);
export const BLOCKS_PER_YEAR = BigInt.fromI64(Math.round((365 as f64) * SECONDS_PER_DAY * BLOCK_TIME) as i64);
export const BLOCKS_PER_WEEK = BigInt.fromI64(Math.round((7 as f64) * SECONDS_PER_DAY / BLOCK_TIME) as i64);
export const BLOCKS_PER_MONTH = BigInt.fromI64(Math.round((30 as f64) * SECONDS_PER_DAY / BLOCK_TIME) as i64);
export const BLOCKS_PER_YEAR = BigInt.fromI64(Math.round((365 as f64) * SECONDS_PER_DAY / BLOCK_TIME) as i64);

/**
* Returns APY in percents scaled by 10 ^ 18
Expand Down
6 changes: 3 additions & 3 deletions packages/subgraph/src/apy/reward-apy-service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Bytes, BigInt } from "@graphprotocol/graph-ts";
import { RewardAPY } from "../../generated/schema"
import {WithLogger} from '../logger'
import { MAX_BPS, BLOCKS_PER_DAY, BLOCKS_PER_WEEK, BLOCKS_PER_MONTH, BLOCKS_PER_YEAR, toApy } from "./apy-calculations";
import { INTEREST_RATE_DECIMALS, BLOCKS_PER_DAY, BLOCKS_PER_WEEK, BLOCKS_PER_MONTH, BLOCKS_PER_YEAR, toApy } from "./apy-calculations";

export interface IRewardApyService {
createOrUpdate(id: Bytes, interestRatePerBlock: BigInt): RewardAPY;
Expand All @@ -18,11 +18,11 @@ export class RewardApyService extends WithLogger implements IRewardApyService {
if(!entity) {
this.logger.info("Creating new APY entity for {}", [id.toString()])
entity = new RewardAPY(id);
entity.decimals = MAX_BPS;
entity.decimals = INTEREST_RATE_DECIMALS;
}

this.logger.info("Filling APY entity for {}", [id.toString()])
entity.dayly = toApy(interestRatePerBlock, BLOCKS_PER_DAY);
entity.daily = toApy(interestRatePerBlock, BLOCKS_PER_DAY);
entity.weekly = toApy(interestRatePerBlock, BLOCKS_PER_WEEK);
entity.monthly = toApy(interestRatePerBlock, BLOCKS_PER_MONTH);
entity.yearly = toApy(interestRatePerBlock, BLOCKS_PER_YEAR);
Expand Down
2 changes: 1 addition & 1 deletion packages/subgraph/tests/.latest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"version": "0.5.4",
"timestamp": 1688083670264
"timestamp": 1688229780947
}
23 changes: 11 additions & 12 deletions packages/subgraph/tests/reward-apy-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { MockLogger, mockViewFunction } from "./mocking"
import { createUpgradedEvent } from "./vault-utils";
import { Context } from "../src/Context";
import { RewardApyService } from "../src/apy/reward-apy-service";
import { MAX_BPS } from "../src/apy/apy-calculations";
import { INTEREST_RATE_DECIMALS } from "../src/apy/apy-calculations";

const tokenAddress = Address.fromString("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
const tokenAddressStr = tokenAddress.toHexString()
Expand Down Expand Up @@ -52,12 +52,11 @@ describe("RewardApyService", () => {

assert.entityCount("RewardAPY", 1)

assert.fieldEquals("RewardAPY", idStr, "decimals", MAX_BPS.toString())
assert.fieldEquals("RewardAPY", idStr, "dayly", "353403600")
assert.fieldEquals("RewardAPY", idStr, "weekly", "22391510400")
assert.fieldEquals("RewardAPY", idStr, "monthly", "95963616000")
assert.fieldEquals("RewardAPY", idStr, "yearly", "1167557328000")

assert.fieldEquals("RewardAPY", idStr, "decimals", INTEREST_RATE_DECIMALS.toString())
assert.fieldEquals("RewardAPY", idStr, "daily", "353403600")
assert.fieldEquals("RewardAPY", idStr, "weekly", "2471439000")
assert.fieldEquals("RewardAPY", idStr, "monthly", "10591899000")
assert.fieldEquals("RewardAPY", idStr, "yearly", "128868034800")
})

test("should update APY entity", () => {
Expand All @@ -70,11 +69,11 @@ describe("RewardApyService", () => {

assert.entityCount("RewardAPY", 1)

assert.fieldEquals("RewardAPY", idStr, "decimals", MAX_BPS.toString())
assert.fieldEquals("RewardAPY", idStr, "dayly", "706807200")
assert.fieldEquals("RewardAPY", idStr, "weekly", "44783020800")
assert.fieldEquals("RewardAPY", idStr, "monthly", "191927232000")
assert.fieldEquals("RewardAPY", idStr, "yearly", "2335114656000")
assert.fieldEquals("RewardAPY", idStr, "decimals", INTEREST_RATE_DECIMALS.toString())
assert.fieldEquals("RewardAPY", idStr, "daily", "706807200")
assert.fieldEquals("RewardAPY", idStr, "weekly", "4942878000")
assert.fieldEquals("RewardAPY", idStr, "monthly", "21183798000")
assert.fieldEquals("RewardAPY", idStr, "yearly", "257736069600")
})

})
Expand Down

0 comments on commit c8e2c54

Please sign in to comment.