diff --git a/bulla-contracts/abis/BullaFactoring.json b/bulla-contracts/abis/BullaFactoring.json index ec5ad8b..09c3668 100644 --- a/bulla-contracts/abis/BullaFactoring.json +++ b/bulla-contracts/abis/BullaFactoring.json @@ -40,6 +40,31 @@ "internalType": "uint16", "name": "_adminFeeBps", "type": "uint16" + }, + { + "internalType": "string", + "name": "_poolName", + "type": "string" + }, + { + "internalType": "uint16", + "name": "_taxBps", + "type": "uint16" + }, + { + "internalType": "uint16", + "name": "_targetYieldBps", + "type": "uint16" + }, + { + "internalType": "string", + "name": "_tokenName", + "type": "string" + }, + { + "internalType": "string", + "name": "_tokenSymbol", + "type": "string" } ], "stateMutability": "nonpayable", @@ -277,6 +302,11 @@ "name": "FunctionNotSupported", "type": "error" }, + { + "inputs": [], + "name": "ImpairReserveMustBeGreater", + "type": "error" + }, { "inputs": [], "name": "InvalidAddress", @@ -287,6 +317,11 @@ "name": "InvalidPercentage", "type": "error" }, + { + "inputs": [], + "name": "InvoiceAlreadyImpairedByFund", + "type": "error" + }, { "inputs": [], "name": "InvoiceAlreadyPaid", @@ -302,6 +337,11 @@ "name": "InvoiceNotApproved", "type": "error" }, + { + "inputs": [], + "name": "InvoiceNotImpaired", + "type": "error" + }, { "inputs": [], "name": "InvoicePaidAmountChanged", @@ -317,6 +357,11 @@ "name": "NoFeesToWithdraw", "type": "error" }, + { + "inputs": [], + "name": "NoTaxBalanceToWithdraw", + "type": "error" + }, { "inputs": [ { @@ -350,6 +395,16 @@ "name": "SafeERC20FailedOperation", "type": "error" }, + { + "inputs": [], + "name": "TaxWithdrawalFailed", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, { "inputs": [ { @@ -589,6 +644,32 @@ "name": "DepositMadeWithAttachment", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "DepositPermissionsChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newAddress", + "type": "address" + } + ], + "name": "FactoringPermissionsChanged", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -615,6 +696,19 @@ "name": "GracePeriodDaysChanged", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newImpairReserve", + "type": "uint256" + } + ], + "name": "ImpairReserveChanged", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -641,6 +735,12 @@ "internalType": "uint256", "name": "validUntil", "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "minDays", + "type": "uint16" } ], "name": "InvoiceApproved", @@ -671,6 +771,31 @@ "name": "InvoiceFunded", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "invoiceId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lossAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "gainAmount", + "type": "uint256" + } + ], + "name": "InvoiceImpaired", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -710,6 +835,18 @@ "internalType": "address", "name": "originalCreditor", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalRefundAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestToCharge", + "type": "uint256" } ], "name": "InvoiceUnfactored", @@ -858,6 +995,57 @@ "name": "SharesRedeemedWithAttachment", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "newTargetYield", + "type": "uint16" + } + ], + "name": "TargetYieldChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TaxBalanceWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint16", + "name": "oldTaxBps", + "type": "uint16" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "newTaxBps", + "type": "uint256" + } + ], + "name": "TaxBpsChanged", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1074,6 +1262,11 @@ "internalType": "uint16", "name": "_upfrontBps", "type": "uint16" + }, + { + "internalType": "uint16", + "name": "minDays", + "type": "uint16" } ], "name": "approveInvoice", @@ -1167,6 +1360,11 @@ "internalType": "uint256", "name": "adminFee", "type": "uint256" + }, + { + "internalType": "uint16", + "name": "minDays", + "type": "uint16" } ], "stateMutability": "view", @@ -1245,7 +1443,7 @@ }, { "inputs": [], - "name": "bullaDaoFeeBalance", + "name": "calculateCapitalAccount", "outputs": [ { "internalType": "uint256", @@ -1257,8 +1455,14 @@ "type": "function" }, { - "inputs": [], - "name": "calculateCapitalAccount", + "inputs": [ + { + "internalType": "uint256", + "name": "invoiceId", + "type": "uint256" + } + ], + "name": "calculateKickbackAmount", "outputs": [ { "internalType": "uint256", @@ -1266,7 +1470,7 @@ "type": "uint256" } ], - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { @@ -1326,6 +1530,25 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "calculateTax", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1364,6 +1587,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "creationTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "decimals", @@ -1487,10 +1723,86 @@ } ], "name": "fundInvoice", - "outputs": [], + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "getFundInfo", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "uint256", + "name": "creationTimestamp", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "fundBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deployedCapital", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "realizedGain", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "capitalAccount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensAvailableForRedemption", + "type": "uint256" + }, + { + "internalType": "uint16", + "name": "adminFeeBps", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "impairReserve", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "targetYieldBps", + "type": "uint256" + } + ], + "internalType": "struct IBullaFactoring.FundInfo", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1523,6 +1835,61 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "invoiceId", + "type": "uint256" + } + ], + "name": "impairInvoice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "impairReserve", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "impairments", + "outputs": [ + { + "internalType": "uint256", + "name": "gainAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lossAmount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isImpaired", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "invoiceProviderAdapter", @@ -1694,6 +2061,25 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "paidInvoiceTax", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1713,6 +2099,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "poolName", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1802,6 +2201,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "protocolFeeBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "protocolFeeBps", @@ -1948,6 +2360,32 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newDepositPermissionsAddress", + "type": "address" + } + ], + "name": "setDepositPermissions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newFactoringPermissionsAddress", + "type": "address" + } + ], + "name": "setFactoringPermissions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1961,6 +2399,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_impairReserve", + "type": "uint256" + } + ], + "name": "setImpairReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1974,6 +2425,32 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "_targetYieldBps", + "type": "uint16" + } + ], + "name": "setTargetYield", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "_newTaxBps", + "type": "uint16" + } + ], + "name": "setTaxBps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -2000,6 +2477,45 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "targetYieldBps", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "taxBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "taxBps", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalAssets", @@ -2013,6 +2529,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "totalFundedAmountForActiveInvoices", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalSupply", @@ -2178,5 +2707,12 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [], + "name": "withdrawTaxBalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ] \ No newline at end of file diff --git a/bulla-contracts/schema.graphql b/bulla-contracts/schema.graphql index 25c609b..6575cb4 100644 --- a/bulla-contracts/schema.graphql +++ b/bulla-contracts/schema.graphql @@ -193,6 +193,8 @@ type InvoiceUnfactoredEvent implements IEventLog @entity { invoiceId: String! originalCreditor: Bytes! #address eventName: String! + totalRefundAmount: BigInt! + interestToCharge: BigInt! blockNumber: BigInt! transactionHash: Bytes! logIndex: BigInt! diff --git a/bulla-contracts/src/mappings/BullaFactoring.ts b/bulla-contracts/src/mappings/BullaFactoring.ts index 4fcb575..6675c93 100644 --- a/bulla-contracts/src/mappings/BullaFactoring.ts +++ b/bulla-contracts/src/mappings/BullaFactoring.ts @@ -84,7 +84,8 @@ export function handleInvoiceUnfactored(event: InvoiceUnfactored): void { InvoiceUnfactoredEvent.blockNumber = event.block.number; InvoiceUnfactoredEvent.transactionHash = event.transaction.hash; InvoiceUnfactoredEvent.logIndex = event.logIndex; - InvoiceUnfactoredEvent.timestamp = event.block.timestamp; + InvoiceUnfactoredEvent.totalRefundAmount = ev.totalRefundAmount; + InvoiceUnfactoredEvent.interestToCharge = ev.interestToCharge; original_creditor.factoringEvents = original_creditor.factoringEvents ? original_creditor.factoringEvents.concat([InvoiceUnfactoredEvent.id]) diff --git a/bulla-contracts/template.yaml b/bulla-contracts/template.yaml index 9f918a4..1acb745 100644 --- a/bulla-contracts/template.yaml +++ b/bulla-contracts/template.yaml @@ -256,7 +256,7 @@ dataSources: handler: handleInvoiceFunded - event: InvoiceKickbackAmountSent(indexed uint256,uint256,indexed address) handler: handleInvoiceKickbackAmountSent - - event: InvoiceUnfactored(indexed uint256,address) + - event: InvoiceUnfactored(indexed uint256,address,uint256,uint256) handler: handleInvoiceUnfactored - event: DepositMade(indexed address,uint256,uint256) handler: handleDepositMade diff --git a/bulla-contracts/tests/BullaFactoring.test.ts b/bulla-contracts/tests/BullaFactoring.test.ts index 07f5dd7..e1e77da 100644 --- a/bulla-contracts/tests/BullaFactoring.test.ts +++ b/bulla-contracts/tests/BullaFactoring.test.ts @@ -85,7 +85,10 @@ test("it handles BullaFactoring events", () => { log.info("✅ should create a InvoiceKickbackAmountSent event", []); - const invoiceUnfactoredEvent = newInvoiceUnfactoredEvent(claimId, originalCreditor); + const totalRefundAmount = BigInt.fromI32(9000); + const interestToCharge = BigInt.fromI32(100); + + const invoiceUnfactoredEvent = newInvoiceUnfactoredEvent(claimId, originalCreditor, totalRefundAmount, interestToCharge); invoiceUnfactoredEvent.block.timestamp = timestamp; invoiceUnfactoredEvent.block.number = blockNum; @@ -94,6 +97,8 @@ test("it handles BullaFactoring events", () => { const invoiceUnfactoredEventId = getInvoiceUnfactoredEventId(claimId, invoiceUnfactoredEvent); assert.fieldEquals("InvoiceUnfactoredEvent", invoiceUnfactoredEventId, "invoiceId", invoiceUnfactoredEvent.params.invoiceId.toString()); assert.fieldEquals("InvoiceUnfactoredEvent", invoiceUnfactoredEventId, "originalCreditor", invoiceUnfactoredEvent.params.originalCreditor.toHexString()); + assert.fieldEquals("InvoiceUnfactoredEvent", invoiceUnfactoredEventId, "totalRefundAmount", invoiceUnfactoredEvent.params.totalRefundAmount.toString()); + assert.fieldEquals("InvoiceUnfactoredEvent", invoiceUnfactoredEventId, "interestToCharge", invoiceUnfactoredEvent.params.interestToCharge.toString()); log.info("✅ should create a InvoiceUnfactored event", []); diff --git a/bulla-contracts/tests/functions/BullaFactoring.testtools.ts b/bulla-contracts/tests/functions/BullaFactoring.testtools.ts index 3079d92..9cbe3a8 100644 --- a/bulla-contracts/tests/functions/BullaFactoring.testtools.ts +++ b/bulla-contracts/tests/functions/BullaFactoring.testtools.ts @@ -35,13 +35,20 @@ export const newInvoiceKickbackAmountSentEvent = (originatingClaimId: BigInt, ki return event; }; -export const newInvoiceUnfactoredEvent = (originatingClaimId: BigInt, originalCreditor: Address): InvoiceUnfactored => { +export const newInvoiceUnfactoredEvent = ( + originatingClaimId: BigInt, + originalCreditor: Address, + totalRefundAmount: BigInt, + interestToCharge: BigInt +): InvoiceUnfactored => { const event: InvoiceUnfactored = changetype(newMockEvent()); const invoiceId = new ethereum.EventParam("invoiceId", toUint256(originatingClaimId)); const originalCreditorParam = new ethereum.EventParam("originalCreditor", toEthAddress(originalCreditor)); + const totalRefundAmountParam = new ethereum.EventParam("totalRefundAmount", toUint256(totalRefundAmount)); + const interestToChargeParam = new ethereum.EventParam("interestToCharge", toUint256(interestToCharge)); - event.parameters = [invoiceId, originalCreditorParam]; + event.parameters = [invoiceId, originalCreditorParam, totalRefundAmountParam, interestToChargeParam]; return event; };