Skip to content

Commit edc191d

Browse files
authored
refactor: LP Contract refactoring, that allows to specify lp tokens receiver and removes error handling (#97)
1 parent 60b7eb9 commit edc191d

File tree

13 files changed

+71
-220
lines changed

13 files changed

+71
-220
lines changed

sources/contracts/core/amm-pool.tact

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ contract AmmPool(
2828
self.rightVault,
2929
msg.leftAmount,
3030
msg.rightAmount,
31-
msg.depositor,
31+
msg.lpTokensReceiver,
3232
msg.contractId,
33-
0,
33+
false,
34+
false,
3435
null,
3536
null,
3637
);
@@ -77,7 +78,7 @@ contract AmmPool(
7778
body: PayoutFromPool {
7879
otherVault: self.leftVault,
7980
amount: msg.rightAmount - expectedRightAmount,
80-
receiver: msg.depositor,
81+
receiver: msg.lpTokensReceiver,
8182
payloadToForward: msg.rightAdditionalParams.payloadOnSuccess,
8283
}.toCell(),
8384
});
@@ -100,7 +101,7 @@ contract AmmPool(
100101
payloadToForward: msg.leftAdditionalParams.payloadOnSuccess,
101102
otherVault: self.rightVault,
102103
amount: msg.leftAmount - expectedLeftAmount,
103-
receiver: msg.depositor,
104+
receiver: msg.lpTokensReceiver,
104105
}.toCell(),
105106
});
106107
}
@@ -139,12 +140,12 @@ contract AmmPool(
139140
value: 0,
140141
bounce: true,
141142
mode: SendRemainingBalance,
142-
init: getJettonWalletInit(msg.depositor),
143+
init: getJettonWalletInit(msg.lpTokensReceiver),
143144
body: MintViaJettonTransferInternal {
144145
queryId: 0,
145146
amount: liquidityTokensToMint,
146147
sender: myAddress(),
147-
responseDestination: msg.depositor,
148+
responseDestination: msg.lpTokensReceiver,
148149
// Thanks to this flag, we can send all TONs in notify
149150
sendAllTonsInNotifyFlag: true,
150151
// due to the flag above, we can use 0 here
@@ -469,7 +470,7 @@ contract AmmPool(
469470
body: PayoutFromPool {
470471
otherVault: self.rightVault,
471472
amount: msg.rightAmount,
472-
receiver: msg.depositor,
473+
receiver: msg.lpTokensReceiver,
473474
payloadToForward: msg.leftAdditionalParams.payloadOnFailure,
474475
}.toCell(),
475476
});
@@ -481,7 +482,7 @@ contract AmmPool(
481482
body: PayoutFromPool {
482483
otherVault: self.leftVault,
483484
amount: msg.leftAmount,
484-
receiver: msg.depositor,
485+
receiver: msg.lpTokensReceiver,
485486
payloadToForward: msg.rightAdditionalParams.payloadOnFailure,
486487
}.toCell(),
487488
});

sources/contracts/core/liquidity-deposit.tact

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ contract LiquidityDepositContract(
2020
rightVault: Address,
2121
leftSideAmount: Int as coins,
2222
rightSideAmount: Int as coins,
23-
depositor: Address, // This and the next field are kind of salt, so several similar contracts can exist
23+
lpTokensReceiver: Address, // This and the next field are kind of salt, so several similar contracts can exist
2424
contractId: Int as uint64,
25-
status: Int as uint3, // Should be deployed with 0.
25+
leftSideFilled: Bool,
26+
rightSideFilled: Bool,
2627
// 0 - not started
2728
// 1 - left side is filled
2829
// 2 - right side is filled
@@ -33,46 +34,20 @@ contract LiquidityDepositContract(
3334
) {
3435
receive(msg: PartHasBeenDeposited) {
3536
let sender = sender();
37+
// If corresponding side is already filled - we don't care.
38+
// User shouldn't top up the same side again.
3639
if (sender == self.leftVault) {
37-
require(msg.depositor == self.depositor, "LP Deposit: Depositor must be the same");
38-
if ((self.status & 1) != 0 || msg.amount != self.leftSideAmount) {
39-
message(MessageParameters {
40-
mode: SendRemainingValue,
41-
body: RejectLiquidityPart {
42-
depositor: msg.depositor,
43-
amountToReturn: msg.amount,
44-
}.toCell(),
45-
value: 0,
46-
to: sender(),
47-
bounce: false,
48-
});
49-
commit();
50-
require(false, "LP Deposit: Left side cannot be filled again or with different amount");
51-
}
40+
require(msg.amount == self.leftSideAmount, "LP Deposit: Left side cannot be filled with different amount");
5241
self.leftAdditionalParams = msg.additionalParams;
53-
self.status |= 1;
42+
self.leftSideFilled = true;
5443
} else if (sender == self.rightVault) {
55-
require(msg.depositor == self.depositor, "LP Deposit: Depositor must be the same");
56-
if ((self.status & 2) != 0 || msg.amount != self.rightSideAmount) {
57-
message(MessageParameters {
58-
mode: SendRemainingValue,
59-
body: RejectLiquidityPart {
60-
depositor: msg.depositor,
61-
amountToReturn: msg.amount,
62-
}.toCell(),
63-
value: 0,
64-
to: sender(),
65-
bounce: false,
66-
});
67-
commit();
68-
require(false, "LP Deposit: Right side cannot be filled again or with different amount");
69-
}
44+
require(msg.amount == self.rightSideAmount, "LP Deposit: Right side cannot be filled with different amount");
7045
self.rightAdditionalParams = msg.additionalParams;
71-
self.status |= 2;
46+
self.rightSideFilled = true;
7247
}
7348
require(self.leftVault != self.rightVault, "LP Deposit: Vaults must be different");
7449
// Both sides are filled, we can deposit now.
75-
if (self.status == 3) {
50+
if (self.leftSideFilled && self.rightSideFilled) {
7651
// We must check, that this account was deployed with sorted vault, otherwise it could be a security issue
7752
let sortedAddresses = sortAddresses(self.leftVault, self.rightVault);
7853
require(sortedAddresses.lower == self.leftVault, "LP Deposit: Vaults MUST be sorted, to not break invariant");
@@ -92,7 +67,7 @@ contract LiquidityDepositContract(
9267
}.toCell(),
9368
},
9469
body: LiquidityDeposit {
95-
depositor: self.depositor,
70+
lpTokensReceiver: self.lpTokensReceiver,
9671
contractId: self.contractId,
9772
leftAmount: self.leftSideAmount,
9873
rightAmount: self.rightSideAmount,
@@ -107,7 +82,15 @@ contract LiquidityDepositContract(
10782
cashback(sender());
10883
}
10984

110-
get fun status(): Int {
111-
return self.status;
85+
get fun status(): Status {
86+
return Status {
87+
leftSideFilled: self.leftSideFilled,
88+
rightSideFilled: self.rightSideFilled,
89+
};
11290
}
11391
}
92+
93+
struct Status {
94+
leftSideFilled: Bool;
95+
rightSideFilled: Bool;
96+
}

sources/contracts/core/messages.tact

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ message(0x74f7a60) PayoutFromPool {
2929
// We are using USDT-like mint opcode for liquidity deposit
3030
// So this operation will be nicely displayed in Tonviewer
3131
message(0x642b7d07) LiquidityDeposit {
32-
depositor: Address;
32+
lpTokensReceiver: Address;
3333
contractId: Int as uint64;
3434
leftAmount: Int as coins;
3535
rightAmount: Int as coins;

sources/contracts/infra/factory.tact

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ struct LPDepositParams {
2121
secondVault: Address;
2222
firstAmount: Int as coins;
2323
secondAmount: Int as coins;
24-
depositor: Address; // This and the next field are kind of salt; so several similar contracts can exist
24+
lpTokensReceiver: Address; // This and the next field are kind of salt; so several similar contracts can exist
2525
// This contractId should be unique for each liquidity deposit action, one can use LT of a contact
2626
contractId: Int as uint64;
2727
}
@@ -98,15 +98,15 @@ contract Factory() {
9898
secondVault: Address,
9999
firstAmount: Int,
100100
secondAmount: Int,
101-
depositor: Address,
101+
lpTokensReceiver: Address,
102102
contractId: Int,
103103
): Address {
104104
return performAddrRequest(LPDepositAddrRequestId, LPDepositParams {
105105
firstVault,
106106
secondVault,
107107
firstAmount,
108108
secondAmount,
109-
depositor,
109+
lpTokensReceiver,
110110
contractId,
111111
}.toCell());
112112
}
@@ -144,9 +144,10 @@ fun performAddrRequest(requestId: Int, request: Cell): Address {
144144
sortedAddressesAndCoins.higher,
145145
sortedAddressesAndCoins.lowerCoins,
146146
sortedAddressesAndCoins.higherCoins,
147-
params.depositor,
147+
params.lpTokensReceiver,
148148
params.contractId,
149-
0,
149+
false,
150+
false,
150151
null,
151152
null,
152153
));

sources/contracts/vaults/jetton-vault.tact

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -160,27 +160,6 @@ contract JettonVault(
160160
});
161161
}
162162

163-
override fun handleRejectLP(msg: RejectLiquidityPart) {
164-
let ctx = context();
165-
// Actually ctx.value - priceOfJettonForward() is always >= 0 because we require ctx.value >= priceOfJettonForward() in LPDepositPart
166-
let maxFwdAmount = max(0, ctx.value - priceOfJettonForward(ctx.readForwardFee(), 1));
167-
message(MessageParameters {
168-
mode: SendRemainingValue,
169-
body: SendViaJettonTransfer {
170-
queryId: 0,
171-
amount: msg.amountToReturn,
172-
destination: msg.depositor,
173-
responseDestination: msg.depositor,
174-
customPayload: null,
175-
forwardTonAmount: maxFwdAmount,
176-
forwardPayload: sliceWithOneZeroBit(),
177-
}.toCell(),
178-
value: 0,
179-
to: self.jettonWallet!!,
180-
bounce: true,
181-
});
182-
}
183-
184163
get fun inited(): Bool {
185164
return self.jettonWallet != null;
186165
}
@@ -265,7 +244,6 @@ inline fun actionHandler(msg: JettonNotifyWithActionRequest): Bool {
265244
value: 0,
266245
mode: SendRemainingValue,
267246
body: PartHasBeenDeposited {
268-
depositor: msg.sender,
269247
amount: msg.amount,
270248
additionalParams: action.additionalParams,
271249
ammPoolCode: codeOf AmmPool,
@@ -286,9 +264,10 @@ inline fun actionHandler(msg: JettonNotifyWithActionRequest): Bool {
286264
sorted.higher,
287265
sorted.lowerCoins,
288266
sorted.higherCoins,
289-
msg.sender,
267+
action.lpTokensReceiver != null ? action.lpTokensReceiver!! : msg.sender,
290268
initData.contractId,
291-
0,
269+
false,
270+
false,
292271
null,
293272
null,
294273
);
@@ -298,7 +277,6 @@ inline fun actionHandler(msg: JettonNotifyWithActionRequest): Bool {
298277
mode: SendRemainingValue,
299278
value: 0,
300279
body: PartHasBeenDeposited {
301-
depositor: msg.sender,
302280
amount: msg.amount,
303281
additionalParams: action.additionalParams,
304282
ammPoolCode: codeOf AmmPool,

sources/contracts/vaults/ton-vault.tact

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ contract TonVault(
145145
body: PartHasBeenDeposited {
146146
additionalParams: msg.additionalParams,
147147
amount: msg.amountIn,
148-
depositor: sender(),
149148
ammPoolCode: codeOf AmmPool,
150149
}.toCell(),
151150
});
@@ -164,9 +163,10 @@ contract TonVault(
164163
sorted.higher,
165164
sorted.lowerCoins,
166165
sorted.higherCoins,
167-
sender(),
166+
msg.lpTokensReceiver != null ? msg.lpTokensReceiver!! : sender(),
168167
initData.contractId,
169-
0,
168+
false,
169+
false,
170170
null,
171171
null,
172172
);
@@ -176,7 +176,6 @@ contract TonVault(
176176
mode: SendBounceIfActionFail | SendRemainingBalance,
177177
value: 0,
178178
body: PartHasBeenDeposited {
179-
depositor: sender(),
180179
amount: msg.amountIn,
181180
additionalParams: msg.additionalParams,
182181
ammPoolCode: codeOf AmmPool,
@@ -185,16 +184,6 @@ contract TonVault(
185184
}
186185
}
187186

188-
override fun handleRejectLP(msg: RejectLiquidityPart) {
189-
message(MessageParameters {
190-
mode: SendRemainingValue,
191-
body: null,
192-
value: msg.amountToReturn,
193-
to: msg.depositor,
194-
bounce: true,
195-
});
196-
}
197-
198187
receive() {
199188
cashback(sender());
200189
}

sources/contracts/vaults/vault-interface.tact

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ const LPDepositPartOpcode: Int = 0x64c08bfc;
6767
struct LPDepositPart {
6868
liquidityDepositContractData: LiquidityDepositEitherAddress;
6969
additionalParams: AdditionalParams;
70+
// If this field is null, then the LP tokens will be sent to the sender of the message
71+
lpTokensReceiver: Address?;
7072
}
7173

7274
message(0x698cba08) SwapRequestTon {
@@ -78,34 +80,21 @@ message(0x1b434676) AddLiquidityPartTon {
7880
amountIn: Int as coins;
7981
liquidityDepositContractData: LiquidityDepositEitherAddress;
8082
additionalParams: AdditionalParams;
83+
// If this field is null, then the LP tokens will be sent to the sender of the message
84+
lpTokensReceiver: Address?;
8185
}
8286

8387
message(0xe7a3475f) PartHasBeenDeposited {
84-
depositor: Address;
8588
amount: Int as coins;
8689
additionalParams: AdditionalParams;
8790
// This field is needed to not add a (LP-Deposit -> AmmPool) dependency
8891
ammPoolCode: Cell;
8992
}
9093

91-
// This message is used when PartHasBeenDeposited is rejected
92-
// We don't forward any payload in this message because PartHasBeenDeposited may occur only as the result of incorrect
93-
// user actions.
94-
message(0xe3b122ab) RejectLiquidityPart {
95-
depositor: Address;
96-
amountToReturn: Int as coins;
97-
}
98-
9994
trait VaultInterface {
10095
receive(msg: PayoutFromPool) {
10196
self.handlePayout(msg);
10297
}
10398

10499
abstract inline fun handlePayout(msg: PayoutFromPool);
105-
106-
receive(msg: RejectLiquidityPart) {
107-
self.handleRejectLP(msg);
108-
}
109-
110-
abstract inline fun handleRejectLP(msg: RejectLiquidityPart);
111100
}

sources/scripts/deploy.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ const main = async () => {
121121
liquidityDepositContract: randomAddress(0), // Mock LP contract address
122122
initData: null,
123123
},
124+
lpTokensReceiver: null,
124125
additionalParams: {
125126
$$type: "AdditionalParams",
126127
minAmountToDeposit: 0n,
@@ -185,7 +186,8 @@ const main = async () => {
185186
amountRight,
186187
deployerWallet.address,
187188
0n,
188-
0n,
189+
false,
190+
false,
189191
null,
190192
null,
191193
)

sources/tests/factory.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ describe("Factory", () => {
8787
secondVault: vaultB,
8888
firstAmount: BigInt(randomLeftSideAmount),
8989
secondAmount: BigInt(randomRightSideAmount),
90-
depositor: randomLPDepositor,
90+
lpTokensReceiver: randomLPDepositor,
9191
contractId: BigInt(randomContractId),
9292
}
9393

@@ -99,7 +99,8 @@ describe("Factory", () => {
9999
sortedAddresses.rightAmount,
100100
randomLPDepositor,
101101
BigInt(randomContractId),
102-
0n,
102+
false,
103+
false,
103104
null,
104105
null,
105106
)

0 commit comments

Comments
 (0)