Skip to content
This repository was archived by the owner on Dec 11, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions projects/boson/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
const protocolDiamondAddress = "0x59A4C19b55193D5a2EAD0065c54af4d516E18Cb5";

const protocolDeploymentBlock = {
polygon: 34258150,
ethereum: 18240548,
base: 25765296,
arbitrum: 321778899,
optimism: 133002790,
};

/** Event topics **/
const fundsDepositedTopic =
"0x862dfcd9710943e66ad8f1f01a99cc98ab5612a09e62ecc68f63fe2e0f86cb0e";
const fundsEncumberedTopic =
"0x8080d30eb13935d67dfdc606fa5e4170aa03ffdfaf40136ef3fa4355c88b19f9";
const offerCreatedTopic_v2_0_0 =
"0x845c99b8425be384387e239b85d44b6cdf63aab6c45c2534f799743e341c74f8";
const offerCreatedTopic_v2_3_0 =
"0xb6a507882e43ec6bae2f276ce4a839f1ca9dcf2da73095eea9e633e96ecf6eb2";
const offerCreatedTopic_v2_4_0 =
"0xa76af238b31b285c9397e2a7c55650ca18a1baf6504de15d7dd1321693144cf7";
const offerCreatedTopic_v2_5_0 =
"0x5235a4f9db2e479e7353e22e7629a4556897ddaf0ab4eaeb9bb8660c8e49a903";
const offerVoidedTopic =
"0xe7c7f2b8b4a6597a3aa617aff2d206ea5507c118fb6d4e54e130279510796fd5";

const buyerCommittedTopic_v2_0_0 =
"0x442279a0d0683a12971990518f9f3f874391650139a762c4e94b23b51f04d94f";
const buyerCommittedTopic_v2_5_0 =
"0xb52015a0ea2e0345baee81bf183c410328b8f8d0cfd380c43006bb84b78fc100";

/** Event definitions **/
/**
* Some event changed over time, but kept their name, so we define multiple versions here
*/
const OfferCreatedEvent_v2_0_0 =
"event OfferCreated(uint256 indexed offerId, uint256 indexed sellerId, (uint256 id, uint256 sellerId, uint256 price, uint256 sellerDeposit, uint256 buyerCancelPenalty, uint256 quantityAvailable, address exchangeToken, string metadataUri, string metadataHash, bool voided) offer, (uint256 validFrom, uint256 validUntil, uint256 voucherRedeemableFrom, uint256 voucherRedeemableUntil) offerDates, (uint256 disputePeriod, uint256 voucherValid, uint256 resolutionPeriod) offerDurations, (uint256 disputeResolverId, uint256 escalationResponsePeriod, uint256 feeAmount, uint256 buyerEscalationDeposit) disputeResolutionTerms, (uint256 protocolFee, uint256 agentFee) offerFees, uint256 indexed agentId, address executedBy)";
const OfferCreatedEvent_v2_3_0 =
"event OfferCreated(uint256 indexed offerId, uint256 indexed sellerId, (uint256 id, uint256 sellerId, uint256 price, uint256 sellerDeposit, uint256 buyerCancelPenalty, uint256 quantityAvailable, address exchangeToken, string metadataUri, string metadataHash, bool voided, uint256 collectionIndex) offer, (uint256 validFrom, uint256 validUntil, uint256 voucherRedeemableFrom, uint256 voucherRedeemableUntil) offerDates, (uint256 disputePeriod, uint256 voucherValid, uint256 resolutionPeriod) offerDurations, (uint256 disputeResolverId, uint256 escalationResponsePeriod, uint256 feeAmount, uint256 buyerEscalationDeposit) disputeResolutionTerms, (uint256 protocolFee, uint256 agentFee) offerFees, uint256 indexed agentId, address executedBy)";
const OfferCreatedEvent_v2_4_0 =
"event OfferCreated(uint256 indexed offerId, uint256 indexed sellerId, (uint256 id, uint256 sellerId, uint256 price, uint256 sellerDeposit, uint256 buyerCancelPenalty, uint256 quantityAvailable, address exchangeToken, uint8 priceType, string metadataUri, string metadataHash, bool voided, uint256 collectionIndex, (address[] recipients, uint256[] bps)[] royaltyInfo) offer, (uint256 validFrom, uint256 validUntil, uint256 voucherRedeemableFrom, uint256 voucherRedeemableUntil) offerDates, (uint256 disputePeriod, uint256 voucherValid, uint256 resolutionPeriod) offerDurations, (uint256 disputeResolverId, uint256 escalationResponsePeriod, uint256 feeAmount, uint256 buyerEscalationDeposit) disputeResolutionTerms, (uint256 protocolFee, uint256 agentFee) offerFees, uint256 indexed agentId, address executedBy)";
const OfferCreatedEvent_v2_5_0 =
"event OfferCreated(uint256 indexed offerId, uint256 indexed sellerId, (uint256 id, uint256 sellerId, uint256 price, uint256 sellerDeposit, uint256 buyerCancelPenalty, uint256 quantityAvailable, address exchangeToken, uint8 priceType, uint8 creator, string metadataUri, string metadataHash, bool voided, uint256 collectionIndex, (address[] recipients, uint256[] bps)[] royaltyInfo, uint256 buyerId) offer, (uint256 validFrom, uint256 validUntil, uint256 voucherRedeemableFrom, uint256 voucherRedeemableUntil) offerDates, (uint256 disputePeriod, uint256 voucherValid, uint256 resolutionPeriod) offerDurations, (uint256 disputeResolverId, uint256 escalationResponsePeriod, uint256 feeAmount, uint256 buyerEscalationDeposit, address mutualizerAddress) disputeResolutionTerms, (uint256 protocolFee, uint256 agentFee) offerFees, uint256 indexed agentId, address executedBy)";
const OfferVoidedEvent =
"event OfferVoided(uint256 indexed offerId, uint256 indexed creatorId, address indexed executedBy)";

const FundsDepositedEvent =
"event FundsDeposited(uint256 indexed entityId, address indexed executedBy, address indexed tokenAddress, uint256 amount)";
const FundsEncumberedEvent =
"event FundsEncumbered(uint256 indexed entityId, address indexed exchangeToken, uint256 amount, address indexed executedBy)";

const BuyerCommittedEvent_v2_0_0 =
"event BuyerCommitted(uint256 indexed offerId, uint256 indexed buyerId, uint256 indexed exchangeId, (uint256 id, uint256 offerId, uint256 buyerId, uint256 finalizedDate, uint8 state) exchange, (uint256 committedDate, uint256 validUntilDate, uint256 redeemedDate, bool expired) voucher, address executedBy)";
const BuyerCommittedEvent_v2_5_0 =
"event BuyerCommitted(uint256 indexed offerId, uint256 indexed buyerId, uint256 indexed exchangeId, (uint256 id, uint256 offerId, uint256 buyerId, uint256 finalizedDate, uint8 state, address mutualizerAddress) exchange, (uint256 committedDate, uint256 validUntilDate, uint256 redeemedDate, bool expired) voucher, address executedBy)";

module.exports = {
protocolDiamondAddress,
protocolDeploymentBlock,
fundsDepositedTopic,
fundsEncumberedTopic,
offerCreatedTopic_v2_0_0,
offerCreatedTopic_v2_3_0,
offerCreatedTopic_v2_4_0,
offerCreatedTopic_v2_5_0,
offerVoidedTopic,
buyerCommittedTopic_v2_0_0,
buyerCommittedTopic_v2_5_0,
OfferCreatedEvent_v2_0_0,
OfferCreatedEvent_v2_3_0,
OfferCreatedEvent_v2_4_0,
OfferCreatedEvent_v2_5_0,
OfferVoidedEvent,
FundsDepositedEvent,
FundsEncumberedEvent,
BuyerCommittedEvent_v2_0_0,
BuyerCommittedEvent_v2_5_0,
};
67 changes: 65 additions & 2 deletions projects/boson/index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,80 @@
const { staking } = require("../helper/staking");

const {
getVoidedOffers,
getOffers,
getCommits,
getDepositedAndEncumberedBalances,
} = require("./utils");

async function tvl(api) {
// Currently Deposited and Encumbered funds.
// Includes all buyer commitments, seller deposits and dispute resolution fees for active exchanges for both Fixed Price and Price Discovery offers.
// It also includes all additional commits as result of Sequential Commitments
await getDepositedAndEncumberedBalances(api);

// Listed offers with uncommitted quantity
const voidedOffers = await getVoidedOffers(api);
const activeOffers = await getOffers(api, voidedOffers);

// Ignore Price Discovery offers. Their price is unknown until commitment. Its contribution to TVL is included in `getEncumberedFunds`.
// Work only with Fixed Price offers from here on.
const fixedPriceOffers = activeOffers.filter(
(i) => i.offer?.priceType !== 1n
); // priceType 1 = Price Discovery

// Get the existing commits to avoid double counting
const commitsByOffer = await getCommits(api);

const tokenBalances = {};
for (const offer of fixedPriceOffers) {
const offerId = BigInt(offer.offerId);

// Calculate the remaining uncommitted quantity
const uncommittedQuantity =
BigInt(offer.offer.quantityAvailable) -
BigInt(commitsByOffer[offerId]?.length || 0);

if (uncommittedQuantity > 0n) {
// continue; // Skip offers with uncommitted quantity
const exchangeToken = offer.offer.exchangeToken;
const price = BigInt(offer.offer.price);

// Use only a single price (ignore quantity) to avoid TVL inflation
// When buyers are committing, the TVL will increase accordingly
tokenBalances[exchangeToken] =
(tokenBalances[exchangeToken] || 0n) + price;
}
}

api.addTokens(Object.keys(tokenBalances), Object.values(tokenBalances));
}

module.exports = {
ethereum: {
tvl: () => ({}),
tvl,
staking: staking(
[
"0x6244bc0d4b661526c0c62c3610571cd1ac9df2dd",
"0xbacc083795846a67b0782327a96622447ddafe6c",
"0x081a52f02e51978ad419dd7894d7ae3555f8bc26",
"0x3ed0c99c8e8eb94438837cc8a08ca3bb187424cf",
"0x3810d9d6685812af6ef4257de0542ecdba9bfd95"
"0x3810d9d6685812af6ef4257de0542ecdba9bfd95",
"0xdDFa9c32CC6Aa3a53cC681fb6f4A65b255324BD3",
],
"0xC477D038d5420C6A9e0b031712f61c5120090de9"
),
},
polygon: {
tvl,
},
base: {
tvl,
},
optimism: {
tvl,
},
arbitrum: {
tvl,
},
};
149 changes: 149 additions & 0 deletions projects/boson/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
const ethers = require("ethers");
const { getLogs } = require("../helper/cache/getLogs");
const { sumTokens2 } = require("../helper/unwrapLPs");

const {
protocolDiamondAddress,
protocolDeploymentBlock,
fundsDepositedTopic,
fundsEncumberedTopic,
offerCreatedTopic_v2_0_0,
offerCreatedTopic_v2_3_0,
offerCreatedTopic_v2_4_0,
offerCreatedTopic_v2_5_0,
offerVoidedTopic,
buyerCommittedTopic_v2_0_0,
buyerCommittedTopic_v2_5_0,
OfferCreatedEvent_v2_0_0,
OfferCreatedEvent_v2_3_0,
OfferCreatedEvent_v2_4_0,
OfferCreatedEvent_v2_5_0,
OfferVoidedEvent,
FundsDepositedEvent,
FundsEncumberedEvent,
BuyerCommittedEvent_v2_0_0,
BuyerCommittedEvent_v2_5_0,
} = require("./constants");

async function getVoidedOffers(api) {
const logs = await getLogs({
api,
target: protocolDiamondAddress,
topics: [offerVoidedTopic],
fromBlock: protocolDeploymentBlock[api.chain],
eventAbi: OfferVoidedEvent,
onlyArgs: true,
extraKey: "offerVoided",
});

return logs.map((i) => BigInt(i.offerId));
}

async function getOffers(api, voidedOffers = []) {
const response = await getLogs({
api,
target: protocolDiamondAddress,
topics: [
[
offerCreatedTopic_v2_0_0,
offerCreatedTopic_v2_3_0,
offerCreatedTopic_v2_4_0,
offerCreatedTopic_v2_5_0,
],
],
fromBlock: protocolDeploymentBlock[api.chain],
extraKey: "offerCreated",
});

// Combine all versions of the OfferCreated event
const iface = new ethers.Interface([
OfferCreatedEvent_v2_0_0,
OfferCreatedEvent_v2_3_0,
OfferCreatedEvent_v2_4_0,
OfferCreatedEvent_v2_5_0,
]);

const parsedLogs = response.map((log) => {
return iface.parseLog(log)?.args;
});

const blockTimestamp = BigInt(api.timestamp);

return parsedLogs.filter(
(i) =>
!voidedOffers.includes(BigInt(i.offerId)) &&
BigInt(i?.offerDates?.validUntil) >= blockTimestamp &&
BigInt(i?.offerDates?.validFrom) < blockTimestamp
);
}

async function getCommits(api) {
const response = await getLogs({
api,
target: protocolDiamondAddress,
topics: [[buyerCommittedTopic_v2_0_0, buyerCommittedTopic_v2_5_0]],
fromBlock: protocolDeploymentBlock[api.chain],
extraKey: "buyerCommitted",
});

// Combine all versions of the BuyerCommitted event
const iface = new ethers.Interface([
BuyerCommittedEvent_v2_0_0,
BuyerCommittedEvent_v2_5_0,
]);

const parsedLogs = response.map((log) => {
return iface.parseLog(log)?.args;
});

const commitsByOffer = {};

for (const commit of parsedLogs) {
const offerId = BigInt(commit.offerId);
if (!commitsByOffer[offerId]) {
commitsByOffer[offerId] = [commit.exchangeId];
} else {
commitsByOffer[offerId].push(commit.exchangeId);
}
}

return commitsByOffer;
}

async function getDepositedAndEncumberedBalances(api) {
const response = await getLogs({
api,
target: protocolDiamondAddress,
topics: [[fundsDepositedTopic, fundsEncumberedTopic]],
fromBlock: protocolDeploymentBlock[api.chain],
extraKey: "incomingFunds",
});

// Combine all versions of the OfferCreated event
const iface = new ethers.Interface([
FundsDepositedEvent,
FundsEncumberedEvent,
]);

const parsedLogs = response.map((log) => {
return iface.parseLog(log)?.args;
});

// Get the token list
const uniqueTokens = new Set(
parsedLogs.map((i) => i.tokenAddress || i.exchangeToken)
);

return sumTokens2({
api,
tokens: Array.from(uniqueTokens),
owner: protocolDiamondAddress,
});
}

module.exports = {
getVoidedOffers,
getOffers,
getCommits,
getDepositedAndEncumberedBalances,
};