@@ -22,6 +22,10 @@ const armFunctions = {
2222 traderate1 : viewFun ( '0xcf1de5d8' , 'traderate1()' , { } , p . uint256 ) ,
2323}
2424
25+ const erc4626Functions = {
26+ convertToAssets : viewFun ( '0x07a2d13a' , 'convertToAssets(uint256)' , { shares : p . uint256 } , p . uint256 ) ,
27+ }
28+
2529class ArmContract extends ContractBase {
2630 traderate0 ( ) {
2731 return this . eth_call ( armFunctions . traderate0 , { } )
@@ -31,12 +35,21 @@ class ArmContract extends ContractBase {
3135 }
3236}
3337
38+ class ERC4626Contract extends ContractBase {
39+ convertToAssets ( shares : bigint ) {
40+ return this . eth_call ( erc4626Functions . convertToAssets , { shares } )
41+ }
42+ }
43+
3444interface ArmConfig {
3545 address : string
3646 symbol0 : string
3747 symbol1 : string
3848 token0 : string
3949 token1 : string
50+ // ERC4626 vault token whose rate needs converting (e.g. sUSDe)
51+ // When set, rates are adjusted by the vault's convertToAssets rate
52+ vaultToken ?: string
4053}
4154
4255// Build lookup from ARM contract address to config
@@ -68,6 +81,7 @@ registerArm({
6881 symbol1 : 'sUSDe' ,
6982 token0 : addresses . tokens . USDe ,
7083 token1 : addresses . tokens . sUSDe ,
84+ vaultToken : addresses . tokens . sUSDe ,
7185} )
7286
7387registerArm ( {
@@ -81,6 +95,26 @@ registerArm({
8195// Cache traderates per ARM address
8296const traderateCache = new Map < string , { traderate0 : bigint ; traderate1 : bigint } > ( )
8397
98+ // Cache vault exchange rate (e.g. sUSDe → USDe)
99+ const vaultRateCache = new Map < string , bigint > ( )
100+ const ONE = 10n ** 18n
101+
102+ type RendererCtx = Parameters < Parameters < typeof registerEventRenderer > [ 1 ] > [ 0 ] [ 'ctx' ]
103+ type RendererBlock = Parameters < Parameters < typeof registerEventRenderer > [ 1 ] > [ 0 ] [ 'log' ] [ 'block' ]
104+
105+ async function getVaultRate ( ctx : RendererCtx , block : RendererBlock , vaultToken : string ) : Promise < bigint > {
106+ const cached = vaultRateCache . get ( vaultToken )
107+ if ( cached ) return cached
108+ try {
109+ const contract = new ERC4626Contract ( ctx , block , vaultToken )
110+ const rate = await contract . convertToAssets ( ONE )
111+ vaultRateCache . set ( vaultToken , rate )
112+ return rate
113+ } catch {
114+ return ONE // Fallback: assume 1:1
115+ }
116+ }
117+
84118async function getTraderates (
85119 ctx : Parameters < Parameters < typeof registerEventRenderer > [ 1 ] > [ 0 ] [ 'ctx' ] ,
86120 block : Parameters < Parameters < typeof registerEventRenderer > [ 1 ] > [ 0 ] [ 'log' ] [ 'block' ] ,
@@ -112,16 +146,27 @@ registerEventRenderer(TraderateChanged.topic, async (params) => {
112146 traderate1 : data . traderate1 ,
113147 } )
114148
149+ // For vault tokens (e.g. sUSDe), adjust rates to show USDe-equivalent value
150+ let sellRate = 10n ** 72n / data . traderate0 // 1e36 precision
151+ let buyRate = data . traderate1 // 1e36 precision
152+ let rateLabel = `${ arm . symbol1 } /${ arm . symbol0 } `
153+
154+ if ( arm . vaultToken ) {
155+ const vaultRate = await getVaultRate ( params . ctx , params . log . block , arm . vaultToken )
156+ // Multiply by vault rate to convert sUSDe amounts to USDe-equivalent
157+ sellRate = ( sellRate * vaultRate ) / ONE
158+ buyRate = ( buyRate * vaultRate ) / ONE
159+ rateLabel = `${ arm . symbol0 } /${ arm . symbol0 } ` // e.g. USDe/USDe
160+ }
161+
115162 renderEventDiscordEmbed ( params , {
116163 fields : [
117164 {
118- name : `${ formatAmount ( 10n ** 72n / data . traderate0 , 36 , { maximumFractionDigits : 8 } ) } ${ arm . symbol1 } /${
119- arm . symbol0
120- } `,
165+ name : `${ formatAmount ( sellRate , 36 , { maximumFractionDigits : 8 } ) } ${ rateLabel } ` ,
121166 value : 'Sell Price' ,
122167 } ,
123168 {
124- name : `${ formatAmount ( data . traderate1 , 36 , { maximumFractionDigits : 8 } ) } ${ arm . symbol1 } / ${ arm . symbol0 } ` ,
169+ name : `${ formatAmount ( buyRate , 36 , { maximumFractionDigits : 8 } ) } ${ rateLabel } ` ,
125170 value : 'Buy Price' ,
126171 } ,
127172 ] ,
@@ -180,6 +225,18 @@ registerEventRenderer(erc20Abi.events.Transfer.topic, async (params) => {
180225 rate = Number ( rates . traderate1 ) / 1e36
181226 }
182227
228+ // For vault tokens, convert output to underlying-equivalent for rate display
229+ if ( arm . vaultToken ) {
230+ const vaultRate = await getVaultRate ( params . ctx , params . log . block , arm . vaultToken )
231+ if ( isToken0In ) {
232+ // Output is in vault token (sUSDe), convert to USDe-equivalent for rate
233+ rate = ( rate * Number ( vaultRate ) ) / 1e18
234+ } else {
235+ // Input is vault token (sUSDe), adjust rate
236+ rate = ( rate * 1e18 ) / Number ( vaultRate )
237+ }
238+ }
239+
183240 fields . push ( {
184241 name : formatAmount ( outAmount , 18 , { maximumFractionDigits : 6 } ) ,
185242 value : `${ outSymbol } out` ,
0 commit comments