Skip to content

Commit 5229bf3

Browse files
g1nt0kibhjiwonoh
andauthored
Factorial (DefiLlama#13363)
Co-authored-by: alan <[email protected]>
1 parent 89ce611 commit 5229bf3

File tree

2 files changed

+204
-0
lines changed

2 files changed

+204
-0
lines changed

projects/factorial/index.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
const { call } = require("../helper/chain/ton");
2+
const { processTVMSliceReadAddress } = require("./utils");
3+
const ADDRESSES = require("../helper/coreAssets.json");
4+
const { methodology } = require('../helper/aave')
5+
6+
const factorial_ton = "EQDIKEz2BYLnTRWo5W5a6moZ9PXNtyOVOFF7noi8Ufv3axz_";
7+
const market_main = "EQCrEHHG4Ff8TD3PzuH5tFSwHBD3zxeXaosz48jGLebwiiNx"
8+
9+
async function tvl(api) {
10+
const pool_data = await call({ target: market_main, abi: "get_pool_data" })
11+
12+
const _kv = 1;
13+
const assetDicIdx = 13;
14+
const supplyAmountIdx = 4;
15+
const borrowAmountIdx = 5;
16+
const addressIdx = 15;
17+
18+
const assets = pool_data[assetDicIdx][_kv]["elements"];
19+
20+
assets.forEach((asset) => {
21+
const assetInfo = asset["tuple"]["elements"];
22+
const supplied = assetInfo[supplyAmountIdx]["number"]["number"];
23+
const borrowed = assetInfo[borrowAmountIdx]["number"]["number"];
24+
const address = assetInfo[addressIdx]["slice"]["bytes"];
25+
26+
const assetAddress = processTVMSliceReadAddress(address);
27+
const addressToAdd = assetAddress === factorial_ton ? ADDRESSES.ton.TON : assetAddress;
28+
29+
api.add(addressToAdd, supplied - borrowed);
30+
});
31+
}
32+
33+
async function borrowed(api) {
34+
const pool_data = await call({ target: market_main, abi: "get_pool_data" })
35+
36+
const _kv = 1;
37+
const assetDicIdx = 13;
38+
const borrowAmountIdx = 5;
39+
const addressIdx = 15;
40+
41+
const assets = pool_data[assetDicIdx][_kv]["elements"];
42+
43+
assets.forEach((asset) => {
44+
const assetInfo = asset["tuple"]["elements"];
45+
const borrowed = assetInfo[borrowAmountIdx]["number"]["number"];
46+
const address = assetInfo[addressIdx]["slice"]["bytes"];
47+
48+
const assetAddress = processTVMSliceReadAddress(address);
49+
const addressToAdd = assetAddress === factorial_ton ? ADDRESSES.ton.TON : assetAddress;
50+
51+
api.add(addressToAdd, borrowed);
52+
});
53+
}
54+
55+
module.exports = {
56+
methodology,
57+
timetravel: false,
58+
ton: {
59+
tvl, borrowed,
60+
}
61+
}

projects/factorial/utils.js

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
function processTVMSliceReadAddress(base64String) {
2+
let buffer = decodeBase64(base64String);
3+
let { offset, root, index, cellData } = parseBoc(buffer);
4+
let { wc, addressHash } = parseAddress(buffer, offset);
5+
return serializeAddress(wc, addressHash);
6+
}
7+
8+
function decodeBase64(base64String) {
9+
const buffer = Buffer.from(base64String, 'base64');
10+
return buffer;
11+
}
12+
13+
function parseBoc(buffer) {
14+
if (buffer.length < 4) {
15+
throw new Error("Buffer is too short to contain magic bytes");
16+
}
17+
18+
const magic = buffer.readUInt32BE(0);
19+
if (magic !== 0xb5ee9c72) {
20+
throw new Error("Invalid magic");
21+
}
22+
23+
let offset = 4;
24+
25+
let hasIdx = (buffer[offset] >> 7) & 1;
26+
let hasCrc32c = (buffer[offset] >> 6) & 1;
27+
let hasCacheBits = (buffer[offset] >> 5) & 1;
28+
let flags = (buffer[offset] >> 3) & 0b11; // 2 bits
29+
let size = buffer[offset] & 0b111; // 3 bits
30+
offset++;
31+
32+
let offBytes = buffer.readUInt8(offset);
33+
offset++;
34+
35+
let cells = buffer.readUIntBE(offset, size);
36+
offset += size;
37+
38+
let roots = buffer.readUIntBE(offset, size);
39+
offset += size;
40+
41+
let absent = buffer.readUIntBE(offset, size);
42+
offset += size;
43+
44+
let totalCellSize = buffer.readUIntBE(offset, offBytes);
45+
offset += offBytes;
46+
47+
let root = [];
48+
for (let i = 0; i < roots; i++) {
49+
root.push(buffer.readUIntBE(offset, size));
50+
offset += size;
51+
}
52+
53+
let index = null;
54+
if (hasIdx) {
55+
index = buffer.slice(offset, offset + cells * offBytes);
56+
offset += cells * offBytes;
57+
}
58+
59+
let cellData = buffer.slice(offset, offset + totalCellSize);
60+
offset += totalCellSize;
61+
62+
return { offset, root, index, cellData };
63+
}
64+
65+
function parseAddress(buffer, offset) {
66+
const wcByteOffset = 13;
67+
const wcBitsOffset = 3;
68+
let reader = new BitReader(buffer, wcByteOffset, wcBitsOffset);
69+
70+
let wc = (reader.readBits(5) << 3) | (reader.readBits(3));
71+
let addressHash = reader.readBytes(32);
72+
73+
return { wc, addressHash, offset: reader.byteOffset };
74+
}
75+
76+
function serializeAddress(wc, addressHash) {
77+
const bounceableTag = 0x11;
78+
let fullAddress = Buffer.alloc(36);
79+
fullAddress[0] = bounceableTag;
80+
fullAddress[1] = wc;
81+
addressHash.copy(fullAddress, 2);
82+
83+
let crc16 = computeCRC16(fullAddress.slice(0, 34));
84+
fullAddress.writeUInt16BE(crc16, 34);
85+
86+
return fullAddress.toString('base64').replace(/\+/g, '-').replace(/\//g, '_');
87+
}
88+
89+
function computeCRC16(buffer) {
90+
let crc = 0x0000;
91+
let polynomial = 0x1021;
92+
93+
for (let i = 0; i < buffer.length; i++) {
94+
crc ^= buffer[i] << 8;
95+
for (let j = 0; j < 8; j++) {
96+
if (crc & 0x8000) {
97+
crc = (crc << 1) ^ polynomial;
98+
} else {
99+
crc <<= 1;
100+
}
101+
}
102+
crc &= 0xFFFF;
103+
}
104+
return crc;
105+
}
106+
107+
class BitReader {
108+
constructor(buffer, startByte = 0, startBit = 0) {
109+
this.buffer = buffer;
110+
this.byteOffset = startByte;
111+
this.bitOffset = startBit;
112+
}
113+
114+
readBits(n) {
115+
let value = 0;
116+
117+
for (let i = 0; i < n; i++) {
118+
if (this.byteOffset >= this.buffer.length) {
119+
throw new Error("Buffer overflow while reading bits");
120+
}
121+
122+
let bit = (this.buffer[this.byteOffset] >> (7 - this.bitOffset)) & 1;
123+
value = (value << 1) | bit;
124+
125+
this.bitOffset++;
126+
if (this.bitOffset === 8) {
127+
this.bitOffset = 0;
128+
this.byteOffset++;
129+
}
130+
}
131+
return value;
132+
}
133+
134+
readBytes(n) {
135+
let bytes = Buffer.alloc(n);
136+
for (let i = 0; i < n; i++) {
137+
bytes[i] = this.readBits(8);
138+
}
139+
return bytes;
140+
}
141+
}
142+
143+
module.exports = { processTVMSliceReadAddress }

0 commit comments

Comments
 (0)