Skip to content

Commit

Permalink
Add info to unfactoring and add missing pnl entries (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
bengobeil authored Oct 30, 2024
1 parent 5b79039 commit beab830
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 10 deletions.
4 changes: 4 additions & 0 deletions bulla-contracts/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ type InvoiceUnfactoredEvent implements IEventLog & IPoolTransaction @entity {
eventName: String!
totalRefundAmount: BigInt!
interestToCharge: BigInt!
trueInterest: BigInt!
trueProtocolFee: BigInt!
trueAdminFee: BigInt!
trueTax: BigInt!
blockNumber: BigInt!
transactionHash: Bytes!
logIndex: BigInt!
Expand Down
8 changes: 4 additions & 4 deletions bulla-contracts/src/functions/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ export const getOrCreatePoolProfitAndLoss = (event: ethereum.Event, pnl: BigInt)
poolPnl.pnlHistory = [];
}

const pnlHistoryEntryId = poolPnl.id.concat("-").concat(event.block.timestamp.toString());
const pnlHistoryEntryId = poolPnl.id.concat("-").concat(event.transaction.hash.toString()).concat("-").concat(event.logIndex.toString());
const pnlHistoryEntry = new PnlHistoryEntry(pnlHistoryEntryId);
pnlHistoryEntry.timestamp = event.block.timestamp;
pnlHistoryEntry.pnl = pnl;
Expand Down Expand Up @@ -345,7 +345,7 @@ export const getTrueFeesAndTaxesV1 = (poolAddress: Address, invoiceId: BigInt):
const targetFees = getTargetFeesAndTaxes(poolAddress, "v1", invoiceId);
const adminFee = targetFees[2]; // in v1 realisedAdminFee = targetAdminFee
const paidTax = BullaFactoring.bind(poolAddress).paidInvoiceTax(invoiceId);
const trueInterest = BullaFactoring.bind(poolAddress).paidInvoicesGain(invoiceId);
const trueNetInterest = BullaFactoring.bind(poolAddress).paidInvoicesGain(invoiceId);

/* we can't assume no kickback for V1, because they can repay a 100% upfront invoice early and get some of the targetInterest back.
So instead, let's do a rule of three:
Expand All @@ -355,8 +355,8 @@ export const getTrueFeesAndTaxesV1 = (poolAddress: Address, invoiceId: BigInt):
targetInterest (gross) trueInterestNet + paidTax
*/
const trueProcotolFee = targetFees[1] // targetProcotolFee
.times(trueInterest.plus(paidTax))
.times(trueNetInterest.plus(paidTax))
.div(targetFees[0]); // targetInterest

return [trueInterest, trueProcotolFee, adminFee, paidTax];
return [trueNetInterest, trueProcotolFee, adminFee, paidTax];
};
56 changes: 50 additions & 6 deletions bulla-contracts/src/mappings/BullaFactoring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { BigInt } from "@graphprotocol/graph-ts";
import { DepositMade, InvoiceUnfactored as InvoiceUnfactoredV1, SharesRedeemed } from "../../generated/BullaFactoring/BullaFactoring";
import {
ActivePaidInvoicesReconciled,
BullaFactoringv2,
Deposit,
DepositMadeWithAttachment,
InvoiceFunded,
Expand Down Expand Up @@ -201,6 +202,14 @@ export function handleInvoiceUnfactoredV1(event: InvoiceUnfactoredV1): void {
const underlyingClaim = getClaim(originatingClaimId.toString());
const InvoiceUnfactoredEvent = createInvoiceUnfactoredEventv1(originatingClaimId, event);

const targetFees = getTargetFeesAndTaxes(event.address, "v1", ev.invoiceId);

const trueProcotolFee = targetFees[1] // targetProcotolFee
.times(ev.interestToCharge)
.div(targetFees[0]); // targetInterest

const trueTax = calculateTax(event.address, "v1", ev.interestToCharge);

InvoiceUnfactoredEvent.invoiceId = underlyingClaim.id;
InvoiceUnfactoredEvent.originalCreditor = ev.originalCreditor;
const original_creditor = getOrCreateUser(ev.originalCreditor);
Expand All @@ -214,6 +223,10 @@ export function handleInvoiceUnfactoredV1(event: InvoiceUnfactoredV1): void {
InvoiceUnfactoredEvent.logIndex = event.logIndex;
InvoiceUnfactoredEvent.totalRefundAmount = ev.totalRefundAmount;
InvoiceUnfactoredEvent.interestToCharge = ev.interestToCharge;
InvoiceUnfactoredEvent.trueInterest = ev.interestToCharge;
InvoiceUnfactoredEvent.trueAdminFee = targetFees[2];
InvoiceUnfactoredEvent.trueProtocolFee = trueProcotolFee;
InvoiceUnfactoredEvent.trueTax = trueTax;
InvoiceUnfactoredEvent.timestamp = event.block.timestamp;
InvoiceUnfactoredEvent.poolAddress = event.address;
InvoiceUnfactoredEvent.priceAfterTransaction = latestPrice;
Expand All @@ -223,10 +236,13 @@ export function handleInvoiceUnfactoredV1(event: InvoiceUnfactoredV1): void {
? original_creditor.factoringEvents.concat([InvoiceUnfactoredEvent.id])
: [InvoiceUnfactoredEvent.id];

const pool_pnl = getOrCreatePoolProfitAndLoss(event, ev.interestToCharge.minus(trueTax));

InvoiceUnfactoredEvent.save();
original_creditor.save();
price_per_share.save();
historical_factoring_statistics.save();
pool_pnl.save();
}

export function handleInvoiceUnfactoredV2(event: InvoiceUnfactored): void {
Expand All @@ -236,19 +252,40 @@ export function handleInvoiceUnfactoredV2(event: InvoiceUnfactored): void {
const underlyingClaim = getClaim(originatingClaimId.toString());
const InvoiceUnfactoredEvent = createInvoiceUnfactoredEvent(originatingClaimId, event);

const targetFees = getTargetFeesAndTaxes(event.address, "v2", ev.invoiceId);
const approvedInvoice = BullaFactoringv2.bind(event.address).approvedInvoices(ev.invoiceId);

const trueProcotolFee = targetFees[1] // targetProcotolFee
.times(ev.interestToCharge)
.div(targetFees[0]); // targetInterest

const trueTax = calculateTax(event.address, "v2", ev.interestToCharge);

const actualDays = (event.block.timestamp
.minus(approvedInvoice.getFundedTimestamp()))
.div(BigInt.fromI32(3600 * 24));

const adminFee =
actualDays.times(BigInt.fromI32(approvedInvoice.getAdminFeeBps())).times(approvedInvoice.getTrueFaceValue()).div(BigInt.fromI32(365)).div(BigInt.fromI32(10_000));

InvoiceUnfactoredEvent.invoiceId = underlyingClaim.id;
InvoiceUnfactoredEvent.originalCreditor = ev.originalCreditor;
const original_creditor = getOrCreateUser(ev.originalCreditor);
const price_per_share = getOrCreatePricePerShare(event, "v1");
const latestPrice = getLatestPrice(event, "v1");
const historical_factoring_statistics = getOrCreateHistoricalFactoringStatistics(event, "v1");
const price_per_share = getOrCreatePricePerShare(event, "v2");
const latestPrice = getLatestPrice(event, "v2");

const historical_factoring_statistics = getOrCreateHistoricalFactoringStatistics(event, "v2");

InvoiceUnfactoredEvent.eventName = "InvoiceUnfactored";
InvoiceUnfactoredEvent.blockNumber = event.block.number;
InvoiceUnfactoredEvent.transactionHash = event.transaction.hash;
InvoiceUnfactoredEvent.logIndex = event.logIndex;
InvoiceUnfactoredEvent.totalRefundAmount = ev.totalRefundOrPaymentAmount;
InvoiceUnfactoredEvent.interestToCharge = ev.interestToCharge;
InvoiceUnfactoredEvent.trueAdminFee = adminFee;
InvoiceUnfactoredEvent.trueInterest = ev.interestToCharge;
InvoiceUnfactoredEvent.trueProtocolFee = trueProcotolFee;
InvoiceUnfactoredEvent.trueTax = trueTax;
InvoiceUnfactoredEvent.timestamp = event.block.timestamp;
InvoiceUnfactoredEvent.poolAddress = event.address;
InvoiceUnfactoredEvent.priceAfterTransaction = latestPrice;
Expand All @@ -258,10 +295,13 @@ export function handleInvoiceUnfactoredV2(event: InvoiceUnfactored): void {
? original_creditor.factoringEvents.concat([InvoiceUnfactoredEvent.id])
: [InvoiceUnfactoredEvent.id];

const pool_pnl = getOrCreatePoolProfitAndLoss(event, ev.interestToCharge.minus(trueTax));

InvoiceUnfactoredEvent.save();
original_creditor.save();
price_per_share.save();
historical_factoring_statistics.save();
pool_pnl.save();
}

export function handleDepositV2(event: Deposit): void {
Expand Down Expand Up @@ -523,6 +563,7 @@ export function handleInvoiceImpairedV2(event: InvoiceImpaired): void {

export function handleActivePaidInvoicesReconciled(event: ActivePaidInvoicesReconciled, version: string): void {
const ev = event.params;
let pnlTotal = BigInt.fromI32(0);

for (let i = 0; i < ev.paidInvoiceIds.length; i++) {
const invoiceId = ev.paidInvoiceIds[i];
Expand All @@ -536,7 +577,7 @@ export function handleActivePaidInvoicesReconciled(event: ActivePaidInvoicesReco
const latestPrice = getLatestPrice(event, version);

const trueFeesAndTaxes = getTrueFeesAndTaxesV1(event.address, invoiceId);
const trueInterest = trueFeesAndTaxes[0];
const trueNetInterest = trueFeesAndTaxes[0];
const trueProtocolFee = trueFeesAndTaxes[1];
const trueAdminFee = trueFeesAndTaxes[2];
const trueTax = trueFeesAndTaxes[3];
Expand All @@ -550,7 +591,7 @@ export function handleActivePaidInvoicesReconciled(event: ActivePaidInvoicesReco
InvoiceReconciled.poolAddress = event.address;
InvoiceReconciled.priceAfterTransaction = latestPrice;
InvoiceReconciled.claim = invoiceId.toString();
InvoiceReconciled.trueInterest = trueInterest;
InvoiceReconciled.trueInterest = trueNetInterest.plus(trueTax);
InvoiceReconciled.trueProtocolFee = trueProtocolFee;
InvoiceReconciled.trueAdminFee = trueAdminFee;
InvoiceReconciled.trueTax = trueTax;
Expand All @@ -559,13 +600,16 @@ export function handleActivePaidInvoicesReconciled(event: ActivePaidInvoicesReco

InvoiceReconciled.save();
originalCreditor.save();
pnlTotal = pnlTotal.plus(trueNetInterest);
}


const pool_pnl = getOrCreatePoolProfitAndLoss(event, pnlTotal);
const price_per_share = getOrCreatePricePerShare(event, version);
const historical_factoring_statistics = getOrCreateHistoricalFactoringStatistics(event, version);

price_per_share.save();
historical_factoring_statistics.save();
pool_pnl.save();
}

export function handleActivePaidInvoicesReconciledV1(event: ActivePaidInvoicesReconciled): void {
Expand Down

0 comments on commit beab830

Please sign in to comment.