@atomiqlabs/chain-evm 1.0.0-dev.22 → 1.0.0-dev.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/chains/citrea/CitreaBtcRelay.d.ts +21 -0
  2. package/dist/chains/citrea/CitreaBtcRelay.js +43 -0
  3. package/dist/chains/citrea/CitreaChainType.d.ts +4 -4
  4. package/dist/chains/citrea/CitreaFees.d.ts +29 -0
  5. package/dist/chains/citrea/CitreaFees.js +67 -0
  6. package/dist/chains/citrea/CitreaInitializer.d.ts +3 -3
  7. package/dist/chains/citrea/CitreaInitializer.js +15 -8
  8. package/dist/chains/citrea/CitreaSpvVaultContract.d.ts +15 -0
  9. package/dist/chains/citrea/CitreaSpvVaultContract.js +75 -0
  10. package/dist/chains/citrea/CitreaSwapContract.d.ts +22 -0
  11. package/dist/chains/citrea/CitreaSwapContract.js +96 -0
  12. package/dist/chains/citrea/CitreaTokens.d.ts +9 -0
  13. package/dist/chains/citrea/CitreaTokens.js +20 -0
  14. package/dist/evm/btcrelay/EVMBtcRelay.d.ts +8 -1
  15. package/dist/evm/btcrelay/EVMBtcRelay.js +15 -11
  16. package/dist/evm/chain/EVMChainInterface.d.ts +6 -6
  17. package/dist/evm/chain/EVMChainInterface.js +1 -2
  18. package/dist/evm/chain/modules/EVMAddresses.d.ts +1 -0
  19. package/dist/evm/chain/modules/EVMAddresses.js +5 -0
  20. package/dist/evm/chain/modules/EVMFees.d.ts +8 -7
  21. package/dist/evm/chain/modules/EVMFees.js +3 -3
  22. package/dist/evm/chain/modules/EVMTokens.d.ts +2 -0
  23. package/dist/evm/chain/modules/EVMTokens.js +10 -2
  24. package/dist/evm/spv_swap/EVMSpvVaultContract.d.ts +17 -3
  25. package/dist/evm/spv_swap/EVMSpvVaultContract.js +83 -13
  26. package/dist/evm/spv_swap/EVMSpvVaultData.d.ts +1 -0
  27. package/dist/evm/spv_swap/EVMSpvVaultData.js +21 -0
  28. package/dist/evm/swaps/EVMSwapContract.d.ts +4 -4
  29. package/dist/evm/swaps/EVMSwapContract.js +4 -4
  30. package/dist/evm/swaps/modules/EVMLpVault.js +2 -2
  31. package/dist/evm/swaps/modules/EVMSwapClaim.d.ts +1 -0
  32. package/dist/evm/swaps/modules/EVMSwapClaim.js +40 -4
  33. package/dist/evm/swaps/modules/EVMSwapInit.d.ts +3 -3
  34. package/dist/evm/swaps/modules/EVMSwapInit.js +43 -9
  35. package/dist/evm/swaps/modules/EVMSwapRefund.d.ts +2 -2
  36. package/dist/evm/swaps/modules/EVMSwapRefund.js +42 -7
  37. package/dist/index.d.ts +1 -0
  38. package/dist/index.js +1 -0
  39. package/package.json +2 -2
  40. package/src/chains/citrea/CitreaBtcRelay.ts +58 -0
  41. package/src/chains/citrea/CitreaChainType.ts +6 -6
  42. package/src/chains/citrea/CitreaFees.ts +77 -0
  43. package/src/chains/citrea/CitreaInitializer.ts +17 -6
  44. package/src/chains/citrea/CitreaSpvVaultContract.ts +76 -0
  45. package/src/chains/citrea/CitreaSwapContract.ts +103 -0
  46. package/src/chains/citrea/CitreaTokens.ts +22 -0
  47. package/src/evm/btcrelay/EVMBtcRelay.ts +17 -12
  48. package/src/evm/chain/EVMChainInterface.ts +7 -8
  49. package/src/evm/chain/modules/EVMAddresses.ts +6 -0
  50. package/src/evm/chain/modules/EVMFees.ts +10 -11
  51. package/src/evm/chain/modules/EVMTokens.ts +13 -2
  52. package/src/evm/spv_swap/EVMSpvVaultContract.ts +84 -14
  53. package/src/evm/spv_swap/EVMSpvVaultData.ts +24 -1
  54. package/src/evm/swaps/EVMSwapContract.ts +4 -4
  55. package/src/evm/swaps/modules/EVMLpVault.ts +2 -2
  56. package/src/evm/swaps/modules/EVMSwapClaim.ts +36 -4
  57. package/src/evm/swaps/modules/EVMSwapInit.ts +44 -10
  58. package/src/evm/swaps/modules/EVMSwapRefund.ts +38 -7
  59. package/src/index.ts +1 -0
@@ -3,6 +3,7 @@ import {Contract, TransactionRequest} from "ethers";
3
3
  import {ERC20Abi} from "./ERC20Abi";
4
4
  import {EVMAddresses} from "./EVMAddresses";
5
5
  import {EVMFees} from "./EVMFees";
6
+ import {EVMSwapData} from "../../swaps/EVMSwapData";
6
7
 
7
8
 
8
9
  export class EVMTokens extends EVMModule<any> {
@@ -10,8 +11,8 @@ export class EVMTokens extends EVMModule<any> {
10
11
  public static readonly ETH_ADDRESS = "0x0000000000000000000000000000000000000000";
11
12
 
12
13
  public static readonly GasCosts = {
13
- TRANSFER: 80_000,
14
- APPROVE: 80_000
14
+ TRANSFER: 80_000 + 21_000,
15
+ APPROVE: 80_000 + 21_000
15
16
  };
16
17
 
17
18
  private getContract(address: string) {
@@ -112,4 +113,14 @@ export class EVMTokens extends EVMModule<any> {
112
113
  return tx;
113
114
  }
114
115
 
116
+ async getApproveFee(feeRate?: string): Promise<bigint> {
117
+ feeRate ??= await this.root.Fees.getFeeRate();
118
+ return EVMFees.getGasFee(EVMTokens.GasCosts.APPROVE, feeRate);
119
+ }
120
+
121
+ async getTransferFee(feeRate?: string): Promise<bigint> {
122
+ feeRate ??= await this.root.Fees.getFeeRate();
123
+ return EVMFees.getGasFee(EVMTokens.GasCosts.APPROVE, feeRate);
124
+ }
125
+
115
126
  }
@@ -54,11 +54,21 @@ export class EVMSpvVaultContract<ChainId extends string>
54
54
  EVMSpvWithdrawalData
55
55
  >
56
56
  {
57
- private static readonly GasCosts = {
58
- DEPOSIT: 150_000,
59
- OPEN: 100_000,
60
- FRONT: 250_000,
61
- CLAIM: 250_000
57
+ public static readonly GasCosts = {
58
+ DEPOSIT_BASE: 15_000 + 21_000,
59
+ DEPOSIT_ERC20: 40_000,
60
+
61
+ OPEN: 80_000 + 21_000,
62
+
63
+ CLAIM_BASE: 85_000 + 21_000,
64
+ CLAIM_NATIVE_TRANSFER: 7_500,
65
+ CLAIM_ERC20_TRANSFER: 40_000,
66
+ CLAIM_EXECUTION_SCHEDULE: 30_000,
67
+
68
+ FRONT_BASE: 75_000 + 21_000,
69
+ FRONT_NATIVE_TRANSFER: 7_500,
70
+ FRONT_ERC20_TRANSFER: 40_000,
71
+ FRONT_EXECUTION_SCHEDULE: 30_000
62
72
  };
63
73
 
64
74
  readonly chainId: ChainId;
@@ -96,18 +106,26 @@ export class EVMSpvVaultContract<ChainId extends string>
96
106
  }
97
107
 
98
108
  protected async Deposit(signer: string, vault: EVMSpvVaultData, rawAmounts: bigint[], feeRate: string): Promise<TransactionRequest> {
109
+ let totalGas = EVMSpvVaultContract.GasCosts.DEPOSIT_BASE;
99
110
  let value = 0n;
100
- if(vault.token0.token.toLowerCase()===this.Chain.getNativeCurrencyAddress().toLowerCase())
111
+ if(vault.token0.token.toLowerCase()===this.Chain.getNativeCurrencyAddress().toLowerCase()) {
101
112
  value += rawAmounts[0] * vault.token0.multiplier;
102
- if(vault.token1.token.toLowerCase()===this.Chain.getNativeCurrencyAddress().toLowerCase())
113
+ } else {
114
+ if(rawAmounts[0] > 0n) totalGas += EVMSpvVaultContract.GasCosts.DEPOSIT_ERC20;
115
+ }
116
+ if(vault.token1.token.toLowerCase()===this.Chain.getNativeCurrencyAddress().toLowerCase()) {
103
117
  value += (rawAmounts[1] ?? 0n) * vault.token1.multiplier;
118
+ } else {
119
+ if(rawAmounts[1]!=null && rawAmounts[1] > 0n && vault.token0.token.toLowerCase()!==vault.token1.token.toLowerCase())
120
+ totalGas += EVMSpvVaultContract.GasCosts.DEPOSIT_ERC20;
121
+ }
104
122
 
105
123
  const tx = await this.contract.deposit.populateTransaction(
106
124
  vault.owner, vault.vaultId, vault.getVaultParamsStruct(),
107
125
  rawAmounts[0], rawAmounts[1] ?? 0n, { value }
108
126
  );
109
127
  tx.from = signer;
110
- EVMFees.applyFeeRate(tx, EVMSpvVaultContract.GasCosts.DEPOSIT, feeRate);
128
+ EVMFees.applyFeeRate(tx, totalGas, feeRate);
111
129
 
112
130
  return tx;
113
131
  }
@@ -128,7 +146,7 @@ export class EVMSpvVaultContract<ChainId extends string>
128
146
  { value }
129
147
  );
130
148
  tx.from = signer;
131
- EVMFees.applyFeeRate(tx, EVMSpvVaultContract.GasCosts.FRONT, feeRate);
149
+ EVMFees.applyFeeRate(tx, this.getFrontGas(signer, vault, data), feeRate);
132
150
 
133
151
  return tx;
134
152
  }
@@ -143,7 +161,7 @@ export class EVMSpvVaultContract<ChainId extends string>
143
161
  )
144
162
 
145
163
  tx.from = signer;
146
- EVMFees.applyFeeRate(tx, EVMSpvVaultContract.GasCosts.CLAIM, feeRate);
164
+ EVMFees.applyFeeRate(tx, this.getClaimGas(signer, vault, data), feeRate);
147
165
 
148
166
  return tx;
149
167
  }
@@ -520,14 +538,66 @@ export class EVMSpvVaultContract<ChainId extends string>
520
538
  return [tx];
521
539
  }
522
540
 
523
- async getClaimFee(signer: string, withdrawalData: EVMSpvWithdrawalData, feeRate?: string): Promise<bigint> {
541
+ getClaimGas(signer: string, vault: EVMSpvVaultData, data?: EVMSpvWithdrawalData): number {
542
+ let totalGas = EVMSpvVaultContract.GasCosts.CLAIM_BASE;
543
+
544
+ if (data==null || (data.rawAmounts[0] != null && data.rawAmounts[0] > 0n)) {
545
+ const transferFee = vault.token0.token.toLowerCase() === this.Chain.getNativeCurrencyAddress() ?
546
+ EVMSpvVaultContract.GasCosts.CLAIM_NATIVE_TRANSFER : EVMSpvVaultContract.GasCosts.CLAIM_ERC20_TRANSFER;
547
+ totalGas += transferFee;
548
+ if (data==null || data.frontingFeeRate > 0n) totalGas += transferFee; //Also needs to pay out to fronter
549
+ if (data==null || (data.callerFeeRate > 0n && !data.isRecipient(signer))) totalGas += transferFee; //Also needs to pay out to caller
550
+ }
551
+ if (data==null || (data.rawAmounts[1] != null && data.rawAmounts[1] > 0n)) {
552
+ const transferFee = vault.token1.token.toLowerCase() === this.Chain.getNativeCurrencyAddress() ?
553
+ EVMSpvVaultContract.GasCosts.CLAIM_NATIVE_TRANSFER : EVMSpvVaultContract.GasCosts.CLAIM_ERC20_TRANSFER;
554
+ totalGas += transferFee;
555
+ if (data==null || data.frontingFeeRate > 0n) totalGas += transferFee; //Also needs to pay out to fronter
556
+ if (data==null || (data.callerFeeRate > 0n && !data.isRecipient(signer))) totalGas += transferFee; //Also needs to pay out to caller
557
+ }
558
+ if (data==null || (data.executionHash != null && data.executionHash !== ZeroHash)) totalGas += EVMSpvVaultContract.GasCosts.CLAIM_EXECUTION_SCHEDULE;
559
+
560
+ return totalGas;
561
+ }
562
+
563
+ getFrontGas(signer: string, vault: EVMSpvVaultData, data?: EVMSpvWithdrawalData): number {
564
+ let totalGas = EVMSpvVaultContract.GasCosts.FRONT_BASE;
565
+
566
+ if (data==null || (data.rawAmounts[0] != null && data.rawAmounts[0] > 0n)) {
567
+ totalGas += vault.token0.token.toLowerCase() === this.Chain.getNativeCurrencyAddress() ?
568
+ EVMSpvVaultContract.GasCosts.FRONT_NATIVE_TRANSFER : EVMSpvVaultContract.GasCosts.FRONT_ERC20_TRANSFER;
569
+ }
570
+ if (data==null || (data.rawAmounts[1] != null && data.rawAmounts[1] > 0n)) {
571
+ totalGas += vault.token1.token.toLowerCase() === this.Chain.getNativeCurrencyAddress() ?
572
+ EVMSpvVaultContract.GasCosts.FRONT_NATIVE_TRANSFER : EVMSpvVaultContract.GasCosts.FRONT_ERC20_TRANSFER;
573
+ }
574
+ if (data==null || (data.executionHash != null && data.executionHash !== ZeroHash)) totalGas += EVMSpvVaultContract.GasCosts.FRONT_EXECUTION_SCHEDULE;
575
+
576
+ return totalGas;
577
+ }
578
+
579
+ async getClaimFee(signer: string, vault: EVMSpvVaultData, withdrawalData: EVMSpvWithdrawalData, feeRate?: string): Promise<bigint> {
524
580
  feeRate ??= await this.Chain.Fees.getFeeRate();
525
- return EVMFees.getGasFee(EVMSpvVaultContract.GasCosts.CLAIM, feeRate);
581
+ return EVMFees.getGasFee(this.getClaimGas(signer, vault, withdrawalData), feeRate);
526
582
  }
527
583
 
528
- async getFrontFee(signer: string, withdrawalData: EVMSpvWithdrawalData, feeRate?: string): Promise<bigint> {
584
+ async getFrontFee(signer: string, vault?: EVMSpvVaultData, withdrawalData?: EVMSpvWithdrawalData, feeRate?: string): Promise<bigint> {
585
+ vault ??= EVMSpvVaultData.randomVault();
529
586
  feeRate ??= await this.Chain.Fees.getFeeRate();
530
- return EVMFees.getGasFee(EVMSpvVaultContract.GasCosts.FRONT, feeRate);
587
+ let totalFee = EVMFees.getGasFee(this.getFrontGas(signer, vault, withdrawalData), feeRate);
588
+ if(withdrawalData==null || (withdrawalData.rawAmounts[0]!=null && withdrawalData.rawAmounts[0]>0n)) {
589
+ if(vault.token0.token.toLowerCase()!==this.Chain.getNativeCurrencyAddress().toLowerCase()) {
590
+ totalFee += await this.Chain.Tokens.getApproveFee(feeRate);
591
+ }
592
+ }
593
+ if(withdrawalData==null || (withdrawalData.rawAmounts[1]!=null && withdrawalData.rawAmounts[1]>0n)) {
594
+ if(vault.token1.token.toLowerCase()!==this.Chain.getNativeCurrencyAddress().toLowerCase()) {
595
+ if(vault.token1.token.toLowerCase()!==vault.token0.token.toLowerCase() || withdrawalData==null || withdrawalData.rawAmounts[0]==null || withdrawalData.rawAmounts[0]===0n) {
596
+ totalFee += await this.Chain.Tokens.getApproveFee(feeRate);
597
+ }
598
+ }
599
+ }
600
+ return totalFee;
531
601
  }
532
602
 
533
603
  }
@@ -11,8 +11,10 @@ import {
11
11
  SpvVaultParametersStruct,
12
12
  SpvVaultStateStruct
13
13
  } from "./SpvVaultContractTypechain";
14
- import {hexlify} from "ethers";
14
+ import {hexlify, randomBytes} from "ethers";
15
15
  import {AbiCoder, keccak256} from "ethers";
16
+ import {EVMAddresses} from "../chain/modules/EVMAddresses";
17
+ import type {AddressLike, BigNumberish, BytesLike} from "ethers/lib.esm";
16
18
 
17
19
  export function getVaultParamsCommitment(vaultParams: SpvVaultParametersStruct) {
18
20
  return keccak256(AbiCoder.defaultAbiCoder().encode(
@@ -196,6 +198,27 @@ export class EVMSpvVaultData extends SpvVaultData<EVMSpvWithdrawalData> {
196
198
  }
197
199
  }
198
200
 
201
+ static randomVault(): EVMSpvVaultData {
202
+ const spvVaultParams = {
203
+ btcRelayContract: EVMAddresses.randomAddress(),
204
+ token0: EVMAddresses.randomAddress(),
205
+ token1: EVMAddresses.randomAddress(),
206
+ token0Multiplier: 1n,
207
+ token1Multiplier: 1n,
208
+ confirmations: 3n,
209
+ }
210
+ return new EVMSpvVaultData(EVMAddresses.randomAddress(), 0n, {
211
+ spvVaultParametersCommitment: getVaultParamsCommitment(spvVaultParams),
212
+ utxoTxHash: randomBytes(32),
213
+ utxoVout: 0n,
214
+ openBlockheight: 0n,
215
+ withdrawCount: 0n,
216
+ depositCount: 0n,
217
+ token0Amount: 0n,
218
+ token1Amount: 0n
219
+ }, spvVaultParams);
220
+ }
221
+
199
222
  }
200
223
 
201
224
  SpvVaultData.deserializers["EVM"] = EVMSpvVaultData;
@@ -574,16 +574,16 @@ export class EVMSwapContract<ChainId extends string = string>
574
574
  }
575
575
 
576
576
  /**
577
- * Get the estimated solana fee of the commit transaction
577
+ * Get the estimated fee of the commit transaction
578
578
  */
579
- getCommitFee(swapData: EVMSwapData, feeRate?: string): Promise<bigint> {
579
+ getCommitFee(signer: string, swapData: EVMSwapData, feeRate?: string): Promise<bigint> {
580
580
  return this.Init.getInitFee(swapData, feeRate);
581
581
  }
582
582
 
583
583
  /**
584
- * Get the estimated solana transaction fee of the refund transaction
584
+ * Get the estimated transaction fee of the refund transaction
585
585
  */
586
- getRefundFee(swapData: EVMSwapData, feeRate?: string): Promise<bigint> {
586
+ getRefundFee(signer: string, swapData: EVMSwapData, feeRate?: string): Promise<bigint> {
587
587
  return this.Refund.getRefundFee(swapData, feeRate);
588
588
  }
589
589
 
@@ -7,8 +7,8 @@ import {EVMTx} from "../../chain/modules/EVMTransactions";
7
7
  export class EVMLpVault extends EVMSwapModule {
8
8
 
9
9
  private static readonly GasCosts = {
10
- WITHDRAW: 100_000,
11
- DEPOSIT: 100_000
10
+ WITHDRAW: 100_000 + 21_000,
11
+ DEPOSIT: 100_000 + 21_000
12
12
  };
13
13
 
14
14
  /**
@@ -13,8 +13,11 @@ import {EVMBtcStoredHeader} from "../../btcrelay/headers/EVMBtcStoredHeader";
13
13
  export class EVMSwapClaim extends EVMSwapModule {
14
14
 
15
15
  private static readonly GasCosts = {
16
- CLAIM: 120_000,
17
- CLAIM_WITH_SUCCESS_ACTION: 150_000
16
+ BASE: 30_000 + 21_000,
17
+ ERC20_TRANSFER: 40_000,
18
+ NATIVE_TRANSFER: 7500,
19
+ LP_VAULT_TRANSFER: 10_000,
20
+ REPUTATION: 25_000
18
21
  };
19
22
 
20
23
  /**
@@ -37,7 +40,7 @@ export class EVMSwapClaim extends EVMSwapModule {
37
40
  //TODO: Claim with success action not supported yet!
38
41
  const tx = await this.swapContract.claim.populateTransaction(swapData.toEscrowStruct(), witness);
39
42
  tx.from = signer;
40
- EVMFees.applyFeeRate(tx, EVMSwapClaim.GasCosts.CLAIM + (claimHandlerGas ?? 0), feeRate);
43
+ EVMFees.applyFeeRate(tx, this.getClaimGas(swapData) + (claimHandlerGas ?? 0), feeRate);
41
44
  return tx;
42
45
  }
43
46
 
@@ -123,6 +126,35 @@ export class EVMSwapClaim extends EVMSwapModule {
123
126
  return [...initialTxns, claimTx];
124
127
  }
125
128
 
129
+ getClaimGas(swapData: EVMSwapData): number {
130
+ let totalGas = EVMSwapClaim.GasCosts.BASE;
131
+ if(swapData.reputation) totalGas += EVMSwapClaim.GasCosts.REPUTATION;
132
+ if(swapData.isPayOut()) {
133
+ if(swapData.isToken(this.root.getNativeCurrencyAddress())) {
134
+ totalGas += EVMSwapClaim.GasCosts.NATIVE_TRANSFER;
135
+ } else {
136
+ totalGas += EVMSwapClaim.GasCosts.ERC20_TRANSFER;
137
+ }
138
+ } else {
139
+ totalGas += EVMSwapClaim.GasCosts.LP_VAULT_TRANSFER;
140
+ }
141
+ if(swapData.getClaimerBounty() > 0n) {
142
+ if(swapData.isDepositToken(this.root.getNativeCurrencyAddress())) {
143
+ totalGas += EVMSwapClaim.GasCosts.NATIVE_TRANSFER;
144
+ } else {
145
+ totalGas += EVMSwapClaim.GasCosts.ERC20_TRANSFER;
146
+ }
147
+ }
148
+ if(swapData.getSecurityDeposit() > swapData.getClaimerBounty()) {
149
+ if(swapData.isDepositToken(this.root.getNativeCurrencyAddress())) {
150
+ totalGas += EVMSwapClaim.GasCosts.NATIVE_TRANSFER;
151
+ } else {
152
+ totalGas += EVMSwapClaim.GasCosts.ERC20_TRANSFER;
153
+ }
154
+ }
155
+ return totalGas;
156
+ }
157
+
126
158
  /**
127
159
  * Get the estimated starknet transaction fee of the claim transaction
128
160
  */
@@ -130,7 +162,7 @@ export class EVMSwapClaim extends EVMSwapModule {
130
162
  feeRate ??= await this.root.Fees.getFeeRate();
131
163
 
132
164
  //TODO: Claim with success action not supported yet!
133
- let gasRequired = EVMSwapClaim.GasCosts.CLAIM;
165
+ let gasRequired = this.getClaimGas(swapData);
134
166
 
135
167
  const claimHandler: IClaimHandler<any, any> = this.contract.claimHandlersByAddress[swapData.claimHandler.toLowerCase()];
136
168
  if(claimHandler!=null) gasRequired += claimHandler.getGas(swapData);
@@ -1,5 +1,4 @@
1
1
  import {SignatureVerificationError, SwapCommitStateType, SwapDataVerificationError} from "@atomiqlabs/base";
2
- import {Buffer} from "buffer";
3
2
  import { EVMSwapModule } from "../EVMSwapModule";
4
3
  import {EVMSwapData} from "../EVMSwapData";
5
4
  import {keccak256, TransactionRequest, ZeroHash} from "ethers";
@@ -36,8 +35,9 @@ const Initialize = [
36
35
  export class EVMSwapInit extends EVMSwapModule {
37
36
 
38
37
  private static readonly GasCosts = {
39
- INIT: 100_000,
40
- INIT_PAY_IN: 130_000,
38
+ BASE: 45_000 + 21_000,
39
+ ERC20_TRANSFER: 40_000,
40
+ LP_VAULT_TRANSFER: 10_000
41
41
  };
42
42
 
43
43
  /**
@@ -52,13 +52,15 @@ export class EVMSwapInit extends EVMSwapModule {
52
52
  */
53
53
  private async Init(sender: string, swapData: EVMSwapData, timeout: bigint, signature: string, feeRate: string): Promise<TransactionRequest> {
54
54
  let value = 0n;
55
- if(swapData.isToken(this.root.getNativeCurrencyAddress())) value += swapData.getAmount();
55
+ if(swapData.isPayIn()) {
56
+ if(swapData.isOfferer(sender) && swapData.isToken(this.root.getNativeCurrencyAddress())) value += swapData.getAmount();
57
+ }
56
58
  if(swapData.isDepositToken(this.root.getNativeCurrencyAddress())) value += swapData.getTotalDeposit();
57
59
  const tx = await this.swapContract.initialize.populateTransaction(swapData.toEscrowStruct(), signature, timeout, "0x"+(swapData.extraData ?? ""), {
58
60
  value
59
61
  });
60
62
  tx.from = sender;
61
- EVMFees.applyFeeRate(tx, swapData.isPayIn() ? EVMSwapInit.GasCosts.INIT_PAY_IN : EVMSwapInit.GasCosts.INIT, feeRate);
63
+ EVMFees.applyFeeRate(tx, this.getInitGas(swapData), feeRate);
62
64
  return tx;
63
65
  }
64
66
 
@@ -259,7 +261,7 @@ export class EVMSwapInit extends EVMSwapModule {
259
261
 
260
262
  const txs: EVMTx[] = [];
261
263
  const requiredApprovals: {[address: string]: bigint} = {};
262
- if(swapData.payIn && swapData.isOfferer(sender)) {
264
+ if(swapData.isPayIn() && swapData.isOfferer(sender)) {
263
265
  if(!swapData.isToken(this.root.getNativeCurrencyAddress())) {
264
266
  requiredApprovals[swapData.token.toLowerCase()] = swapData.amount;
265
267
  }
@@ -281,12 +283,44 @@ export class EVMSwapInit extends EVMSwapModule {
281
283
  return txs;
282
284
  }
283
285
 
286
+ private getInitGas(swapData: EVMSwapData): number {
287
+ let totalGas = EVMSwapInit.GasCosts.BASE;
288
+ if(swapData.isPayIn()) {
289
+ if(!swapData.isToken(this.root.getNativeCurrencyAddress())) {
290
+ totalGas += EVMSwapInit.GasCosts.ERC20_TRANSFER;
291
+ }
292
+ } else {
293
+ totalGas += EVMSwapInit.GasCosts.LP_VAULT_TRANSFER;
294
+ }
295
+ if(swapData.getTotalDeposit() > 0) {
296
+ if(!swapData.isPayIn() || !swapData.isDepositToken(swapData.token)) {
297
+ if(!swapData.isDepositToken(this.root.getNativeCurrencyAddress())) {
298
+ totalGas += EVMSwapInit.GasCosts.ERC20_TRANSFER;
299
+ }
300
+ }
301
+ }
302
+ return totalGas;
303
+ }
304
+
284
305
  /**
285
- * Get the estimated solana fee of the init transaction, this includes the required deposit for creating swap PDA
286
- * and also deposit for ATAs
306
+ * Get the estimated fee of the init transaction
287
307
  */
288
- async getInitFee(swapData?: EVMSwapData, feeRate?: string): Promise<bigint> {
308
+ async getInitFee(swapData: EVMSwapData, feeRate?: string): Promise<bigint> {
289
309
  feeRate ??= await this.root.Fees.getFeeRate();
290
- return EVMFees.getGasFee(swapData.payIn ? EVMSwapInit.GasCosts.INIT_PAY_IN : EVMSwapInit.GasCosts.INIT, feeRate);
310
+ let totalFee = EVMFees.getGasFee(this.getInitGas(swapData), feeRate);
311
+ if(swapData.isPayIn()) {
312
+ if(!swapData.isToken(this.root.getNativeCurrencyAddress())) {
313
+ totalFee += await this.root.Tokens.getApproveFee(feeRate);
314
+ }
315
+ }
316
+ if(swapData.getTotalDeposit() > 0) {
317
+ if(!swapData.isPayIn() || !swapData.isDepositToken(swapData.token)) {
318
+ if(!swapData.isDepositToken(this.root.getNativeCurrencyAddress())) {
319
+ totalFee += await this.root.Tokens.getApproveFee(feeRate);
320
+ }
321
+ }
322
+ }
323
+
324
+ return totalFee;
291
325
  }
292
326
  }
@@ -17,8 +17,11 @@ const Refund = [
17
17
  export class EVMSwapRefund extends EVMSwapModule {
18
18
 
19
19
  private static readonly GasCosts = {
20
- REFUND: 100_000,
21
- REFUND_PAY_OUT: 130_000
20
+ BASE: 35_000 + 21_000,
21
+ ERC20_TRANSFER: 40_000,
22
+ NATIVE_TRANSFER: 7500,
23
+ LP_VAULT_TRANSFER: 10_000,
24
+ REPUTATION: 25_000
22
25
  };
23
26
 
24
27
  /**
@@ -40,7 +43,7 @@ export class EVMSwapRefund extends EVMSwapModule {
40
43
  ): Promise<TransactionRequest> {
41
44
  const tx = await this.swapContract.refund.populateTransaction(swapData.toEscrowStruct(), witness);
42
45
  tx.from = signer;
43
- EVMFees.applyFeeRate(tx, (swapData.payIn ? EVMSwapRefund.GasCosts.REFUND_PAY_OUT : EVMSwapRefund.GasCosts.REFUND) + (handlerGas ?? 0), feeRate)
46
+ EVMFees.applyFeeRate(tx, this.getRefundGas(swapData) + (handlerGas ?? 0), feeRate)
44
47
  return tx;
45
48
  }
46
49
 
@@ -63,7 +66,7 @@ export class EVMSwapRefund extends EVMSwapModule {
63
66
  ): Promise<TransactionRequest> {
64
67
  const tx = await this.swapContract.cooperativeRefund.populateTransaction(swapData.toEscrowStruct(), signature, BigInt(timeout));
65
68
  tx.from = sender;
66
- EVMFees.applyFeeRate(tx, swapData.payIn ? EVMSwapRefund.GasCosts.REFUND_PAY_OUT : EVMSwapRefund.GasCosts.REFUND, feeRate)
69
+ EVMFees.applyFeeRate(tx, this.getRefundGas(swapData), feeRate)
67
70
  return tx;
68
71
  }
69
72
 
@@ -186,13 +189,41 @@ export class EVMSwapRefund extends EVMSwapModule {
186
189
  return [tx];
187
190
  }
188
191
 
192
+ getRefundGas(swapData: EVMSwapData): number {
193
+ let totalGas = EVMSwapRefund.GasCosts.BASE;
194
+ if(swapData.reputation) totalGas += EVMSwapRefund.GasCosts.REPUTATION;
195
+ if(swapData.isPayIn()) {
196
+ if(swapData.isToken(this.root.getNativeCurrencyAddress())) {
197
+ totalGas += EVMSwapRefund.GasCosts.NATIVE_TRANSFER;
198
+ } else {
199
+ totalGas += EVMSwapRefund.GasCosts.ERC20_TRANSFER;
200
+ }
201
+ } else {
202
+ totalGas += EVMSwapRefund.GasCosts.LP_VAULT_TRANSFER;
203
+ }
204
+ if(swapData.getSecurityDeposit() > 0n) {
205
+ if(swapData.isDepositToken(this.root.getNativeCurrencyAddress())) {
206
+ totalGas += EVMSwapRefund.GasCosts.NATIVE_TRANSFER;
207
+ } else {
208
+ totalGas += EVMSwapRefund.GasCosts.ERC20_TRANSFER;
209
+ }
210
+ }
211
+ if(swapData.getClaimerBounty() > swapData.getSecurityDeposit()) {
212
+ if(swapData.isDepositToken(this.root.getNativeCurrencyAddress())) {
213
+ totalGas += EVMSwapRefund.GasCosts.NATIVE_TRANSFER;
214
+ } else {
215
+ totalGas += EVMSwapRefund.GasCosts.ERC20_TRANSFER;
216
+ }
217
+ }
218
+ return totalGas;
219
+ }
220
+
189
221
  /**
190
- * Get the estimated solana transaction fee of the refund transaction, in the worst case scenario in case where the
191
- * ATA needs to be initialized again (i.e. adding the ATA rent exempt lamports to the fee)
222
+ * Get the estimated transaction fee of the refund transaction
192
223
  */
193
224
  async getRefundFee(swapData: EVMSwapData, feeRate?: string): Promise<bigint> {
194
225
  feeRate ??= await this.root.Fees.getFeeRate();
195
- return EVMFees.getGasFee(swapData.payIn ? EVMSwapRefund.GasCosts.REFUND_PAY_OUT : EVMSwapRefund.GasCosts.REFUND, feeRate);
226
+ return EVMFees.getGasFee(this.getRefundGas(swapData), feeRate);
196
227
  }
197
228
 
198
229
  }
package/src/index.ts CHANGED
@@ -42,3 +42,4 @@ export * from "./evm/wallet/EVMSigner";
42
42
 
43
43
  export * from "./chains/citrea/CitreaInitializer";
44
44
  export * from "./chains/citrea/CitreaChainType";
45
+ export * from "./chains/citrea/CitreaFees";