Skip to content

Commit 6d9cfb0

Browse files
authored
Fix/gsteenkamp custom bond (#106)
* derive custom bond key from currency Signed-off-by: Gerhard Steenkamp <gerhard@umaproject.org> * fixup Signed-off-by: Gerhard Steenkamp <gerhard@umaproject.org> * fixup Signed-off-by: Gerhard Steenkamp <gerhard@umaproject.org> * add test case Signed-off-by: Gerhard Steenkamp <gerhard@umaproject.org> * add some comments Signed-off-by: Gerhard Steenkamp <gerhard@umaproject.org> * fixup Signed-off-by: Gerhard Steenkamp <gerhard@umaproject.org> * update readme Signed-off-by: Gerhard Steenkamp <gerhard@umaproject.org> * remove redundant field Signed-off-by: Gerhard Steenkamp <gerhard@umaproject.org> --------- Signed-off-by: Gerhard Steenkamp <gerhard@umaproject.org>
1 parent b0a18ca commit 6d9cfb0

File tree

6 files changed

+354
-148
lines changed

6 files changed

+354
-148
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ This subgraph indexes events and function calls by the "Managed Optimistic Oracl
146146

147147
- Amoy
148148
- TheGraph:
149-
- Goldsky: <https://api.goldsky.com/api/public/project_clus2fndawbcc01w31192938i/subgraphs/amoy-managed-optimistic-oracle-v2/1.0.5/gn>
149+
- Goldsky: <https://api.goldsky.com/api/public/project_clus2fndawbcc01w31192938i/subgraphs/amoy-managed-optimistic-oracle-v2/1.0.6/gn>
150150
- Polygon
151151
- TheGraph:
152-
- Goldsky: <https://api.goldsky.com/api/public/project_clus2fndawbcc01w31192938i/subgraphs/polygon-managed-optimistic-oracle-v2/1.0.2/gn>
152+
- Goldsky: <https://api.goldsky.com/api/public/project_clus2fndawbcc01w31192938i/subgraphs/polygon-managed-optimistic-oracle-v2/1.0.3/gn>
153153

154154
## Financial Contract Events
155155

packages/managed-oracle-v2/schema.graphql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,11 @@ type OptimisticPriceRequest @entity {
8282
}
8383

8484
type CustomBond @entity {
85-
"ID is managedRequestId, ie. the hash of requester, identifier, ancillaryData"
85+
"ID is the hash of requester, identifier, ancillaryData, currency"
8686
id: ID!
8787

88+
managedRequestId: String!
89+
8890
currency: Bytes!
8991

9092
requester: Bytes!

packages/managed-oracle-v2/src/mappings/managedOracleV2.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
import { log } from "@graphprotocol/graph-ts";
22
import { CustomBond, CustomLiveness } from "../../generated/schema";
33
import { CustomBondSet, CustomLivenessSet } from "../../generated/ManagedOracleV2/ManagedOracleV2";
4-
4+
import { createCustomBondIdFromEvent } from "../utils/helpers/managedOracleV2";
5+
6+
/**
7+
* Handles CustomBondSet events from the ManagedOracleV2 contract.
8+
*
9+
* Creates or updates a CustomBond entity with a unique ID that includes the currency.
10+
* This ensures that custom bonds are tied to specific currencies and can only be
11+
* found when the request currency matches the custom bond currency.
12+
*/
513
export function handleCustomBondSet(event: CustomBondSet): void {
614
const managedRequestId = event.params.managedRequestId.toHexString();
715
log.debug("Custom Bond set event. Loading entity with managedRequestId, {}", [managedRequestId]);
816

9-
let entity = CustomBond.load(managedRequestId);
17+
// Generate unique ID that includes currency - this ensures currency matching
18+
const id = createCustomBondIdFromEvent(event);
19+
20+
let entity = CustomBond.load(id);
1021

1122
if (entity == null) {
12-
entity = new CustomBond(managedRequestId);
23+
entity = new CustomBond(id);
24+
entity.managedRequestId = managedRequestId;
1325
entity.requester = event.params.requester;
1426
entity.identifier = event.params.identifier.toString();
1527
entity.ancillaryData = event.params.ancillaryData.toHex();

packages/managed-oracle-v2/src/mappings/optimisticOracleV2.ts

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,31 @@ import { getManagedRequestId, getOrCreateOptimisticPriceRequest } from "../utils
1212
import { CustomBond, CustomLiveness } from "../../generated/schema";
1313

1414
import { Address, BigInt, Bytes, dataSource, log } from "@graphprotocol/graph-ts";
15+
import { createCustomBondId } from "../utils/helpers/managedOracleV2";
1516

1617
let network = dataSource.network();
1718

1819
let isMainnet = network == "mainnet";
1920
let isGoerli = network == "goerli";
2021

21-
function getCustomBond(requester: Address, identifier: Bytes, ancillaryData: Bytes): CustomBond | null {
22-
const managedRequestId = getManagedRequestId(requester, identifier, ancillaryData).toHexString();
23-
let customBondEntity = CustomBond.load(managedRequestId);
22+
/**
23+
* Retrieves a custom bond entity if one exists for the given parameters.
24+
*
25+
* IMPORTANT: Custom bonds are stored with a unique ID that includes the currency.
26+
* This means we can only find custom bonds that match the EXACT currency used in the request.
27+
* If a custom bond was set for a different currency, it will NOT be found here.
28+
*
29+
* This ensures that custom bonds are only applied when the currency matches,
30+
* preventing incorrect bond amounts from being applied to requests with different currencies.
31+
*/
32+
function getCustomBond(
33+
requester: Address,
34+
identifier: Bytes,
35+
ancillaryData: Bytes,
36+
currency: Bytes
37+
): CustomBond | null {
38+
const id = createCustomBondId(requester, identifier, ancillaryData, currency);
39+
let customBondEntity = CustomBond.load(id);
2440
return customBondEntity ? customBondEntity : null;
2541
}
2642

@@ -118,7 +134,14 @@ export function handleOptimisticRequestPrice(event: RequestPrice): void {
118134
}
119135

120136
// Look up custom bond and liveness values that may have been set before the request
121-
let customBond = getCustomBond(event.params.requester, event.params.identifier, event.params.ancillaryData);
137+
// Custom bonds are stored with a unique ID that includes the currency, so we only find
138+
// custom bonds that match the exact currency used in this request
139+
let customBond = getCustomBond(
140+
event.params.requester,
141+
event.params.identifier,
142+
event.params.ancillaryData,
143+
event.params.currency
144+
);
122145
if (customBond !== null) {
123146
const bond = customBond.customBond;
124147
const currency = customBond.currency;
@@ -127,8 +150,9 @@ export function handleOptimisticRequestPrice(event: RequestPrice): void {
127150
currency.toHexString(),
128151
requestId,
129152
]);
153+
// Apply the custom bond amount - the currency is guaranteed to match since
154+
// the custom bond ID includes the currency and we looked it up using the request's currency
130155
request.bond = bond;
131-
request.currency = currency;
132156
}
133157

134158
let customLiveness = getCustomLiveness(event.params.requester, event.params.identifier, event.params.ancillaryData);
@@ -187,7 +211,14 @@ export function handleOptimisticProposePrice(event: ProposePrice): void {
187211
);
188212

189213
// Look up custom bond and liveness values that may have been set before the request
190-
let customBond = getCustomBond(event.params.requester, event.params.identifier, event.params.ancillaryData);
214+
// Custom bonds are stored with a unique ID that includes the currency, so we only find
215+
// custom bonds that match the exact currency used in this request
216+
let customBond = getCustomBond(
217+
event.params.requester,
218+
event.params.identifier,
219+
event.params.ancillaryData,
220+
event.params.currency
221+
);
191222
if (customBond !== null) {
192223
const bond = customBond.customBond;
193224
const currency = customBond.currency;
@@ -196,8 +227,9 @@ export function handleOptimisticProposePrice(event: ProposePrice): void {
196227
currency.toHexString(),
197228
requestId,
198229
]);
230+
// Apply the custom bond amount - the currency is guaranteed to match since
231+
// the custom bond ID includes the currency and we looked it up using the request's currency
199232
request.bond = bond;
200-
request.currency = currency;
201233
}
202234

203235
let customLiveness = getCustomLiveness(event.params.requester, event.params.identifier, event.params.ancillaryData);
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,36 @@
11
import { Address, ByteArray, Bytes, crypto } from "@graphprotocol/graph-ts";
2+
import { CustomBondSet } from "../../../generated/ManagedOracleV2/ManagedOracleV2";
23

34
export function getManagedRequestId(requester: Address, identifier: Bytes, ancillaryData: Bytes): ByteArray {
45
let packed = requester.concat(identifier).concat(ancillaryData);
56
return crypto.keccak256(packed);
67
}
8+
9+
/**
10+
* Creates a unique ID for a custom bond entity.
11+
*
12+
* Including the currency in the ID ensures that custom bonds are tied to specific currencies.
13+
* This means that custom bonds set for different currencies will have different IDs,
14+
* even if all other parameters (requester, identifier, ancillary data) are the same.
15+
*
16+
* This is crucial for the currency matching logic - we can only find custom bonds
17+
* that match the exact currency used in a request.
18+
*/
19+
export function createCustomBondId(requester: Bytes, identifier: Bytes, ancillaryData: Bytes, currency: Bytes): string {
20+
let packed = requester.concat(identifier).concat(ancillaryData).concat(currency);
21+
return crypto.keccak256(packed).toHexString();
22+
}
23+
24+
/**
25+
* Creates a custom bond ID from a CustomBondSet event.
26+
* This is a convenience function that extracts the parameters from the event
27+
* and passes them to createCustomBondId.
28+
*/
29+
export function createCustomBondIdFromEvent(event: CustomBondSet): string {
30+
return createCustomBondId(
31+
event.params.requester,
32+
event.params.identifier,
33+
event.params.ancillaryData,
34+
event.params.currency
35+
);
36+
}

0 commit comments

Comments
 (0)