diff --git a/helix-contract/contracts/ln/base/LnBridgeTargetV3.sol b/helix-contract/contracts/ln/base/LnBridgeTargetV3.sol index d2f02cf..a33f12a 100644 --- a/helix-contract/contracts/ln/base/LnBridgeTargetV3.sol +++ b/helix-contract/contracts/ln/base/LnBridgeTargetV3.sol @@ -5,7 +5,7 @@ import "../interface/ILnBridgeSourceV3.sol"; import "./LnBridgeHelper.sol"; contract LnBridgeTargetV3 { - // timestamp: the time when transfer filled + // timestamp: the time when transfer filled, this is also the flag that the transfer is filled(relayed or slashed) // provider: the transfer lnProvider struct FillTransfer { uint64 timestamp; @@ -13,6 +13,7 @@ contract LnBridgeTargetV3 { } // lockTimestamp: the time when the transfer start from source chain + // the lockTimestamp is verified on source chain, if slasher falsify this timestamp, then it can't be verified on source chain // sourceAmount: the send amount on source chain struct SlashInfo { uint256 remoteChainId; @@ -143,6 +144,7 @@ contract LnBridgeTargetV3 { _sendMessageToSource(slashInfo.remoteChainId, message, _extParams); } + // can't withdraw for different providers each time function requestWithdrawLiquidity( uint256 _remoteChainId, bytes32[] calldata _transferIds, diff --git a/helix-contract/test/5_test_ln_v3.js b/helix-contract/test/5_test_ln_v3.js index 8c43b4d..cab39b0 100644 --- a/helix-contract/test/5_test_ln_v3.js +++ b/helix-contract/test/5_test_ln_v3.js @@ -366,31 +366,33 @@ describe("lnv3 bridge tests", () => { return slashTransaction; } - async function withdraw(direction, lastTransferId, amount) { + async function withdraw(direction, transferIds, result) { const chainInfo = await getChainInfo(direction); - const providerKey = getProviderKey(chainInfo.dstChainId, relayer.address, chainInfo.srcToken.address, chainInfo.dstToken.address); - const marginBefore = (await chainInfo.srcBridge.srcProviders(providerKey)).config.margin; + + let totalWithdrawAmount = 0; + for (const transferId of transferIds) { + const lockInfo = await chainInfo.srcBridge.lockInfos(transferId); + totalWithdrawAmount += Number(lockInfo.amountWithFeeAndPenalty) - penalty; + } const balanceOfRelayerBefore = await chainInfo.srcToken.balanceOf(relayer.address); - const withdrawTransaction = await chainInfo.dstBridge.connect(relayer).requestWithdrawMargin( + const balanceOfBackingBefore = await chainInfo.srcToken.balanceOf(chainInfo.srcBridge.address); + const withdrawTransaction = await chainInfo.dstBridge.connect(relayer).requestWithdrawLiquidity( chainInfo.srcChainId, - lastTransferId, - chainInfo.srcToken.address, - chainInfo.dstToken.address, - amount, + transferIds, + relayer.address, chainInfo.extParams, ); const balanceOfRelayerAfter = await chainInfo.srcToken.balanceOf(relayer.address); - const marginAfter = (await chainInfo.srcBridge.srcProviders(providerKey)).config.margin; + const balanceOfBackingAfter = await chainInfo.srcToken.balanceOf(chainInfo.srcBridge.address); - let successWithdrawAmount = amount; - if (marginBefore.lt(amount)) { - // if withdraw failed - successWithdrawAmount = 0; + if (result) { + expect(balanceOfRelayerAfter - balanceOfRelayerBefore).to.equal(totalWithdrawAmount); + expect(balanceOfBackingBefore - balanceOfBackingAfter).to.equal(totalWithdrawAmount); + } else { + expect(balanceOfRelayerAfter - balanceOfRelayerBefore).to.equal(0); + expect(balanceOfBackingBefore - balanceOfBackingAfter).to.equal(0); } - expect(balanceOfRelayerAfter - balanceOfRelayerBefore).to.equal(successWithdrawAmount); - expect(marginBefore - marginAfter).to.equal(successWithdrawAmount); - return successWithdrawAmount > 0; } // eth -> arb @@ -419,6 +421,13 @@ describe("lnv3 bridge tests", () => { }); // 2.2. slashed await slash("eth2arb", 2, transferId02, blockTimestamp02); + + // withdraw + await withdraw('eth2arb', [transferId01], true); + // withdraw twice failed + await withdraw('eth2arb', [transferId01], false); + // withdraw a slashed transfer failed + await withdraw('eth2arb', [transferId02], false); } // test arb2eth direction