From 7672727e1cf81492e2b5e3f5e510fec820edf7cf Mon Sep 17 00:00:00 2001 From: wsdt Date: Tue, 23 Apr 2024 00:53:27 +0200 Subject: [PATCH 1/6] feat: Add partial withdraw to contract --- contracts/LightBridge.sol | 6 +++--- test/lightbridge.unit.spec.ts | 30 ++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/contracts/LightBridge.sol b/contracts/LightBridge.sol index 473eaf9..bd773fe 100644 --- a/contracts/LightBridge.sol +++ b/contracts/LightBridge.sol @@ -392,21 +392,21 @@ contract LightBridge is PausableUpgradeable, MulticallUpgradeable { /** * @dev Sends the contract's current balance to the owner. */ - function withdrawBalance(address _token) + function withdrawBalance(address _token, uint256 _amount) external onlyOwner() onlyInitialized() { if (address(0) == _token) { uint256 _balance = address(this).balance; - require(_balance > 0, "Nothing to send"); + require(_balance >= _amount, "Too high"); (bool sent,) = owner.call{gas: 2300, value: _balance}(""); require(sent, "Failed to send Ether"); emit AssetBalanceWithdrawn(_token, owner, _balance); } else { // no supportedToken check in case of generally lost tokens uint256 _balance = IERC20(_token).balanceOf(address(this)); - require(_balance > 0, "Nothing to send"); + require(_balance > _amount, "Too high"); IERC20(_token).safeTransfer(owner, _balance); emit AssetBalanceWithdrawn(_token, owner, _balance); } diff --git a/test/lightbridge.unit.spec.ts b/test/lightbridge.unit.spec.ts index b3732ba..e90dbb7 100644 --- a/test/lightbridge.unit.spec.ts +++ b/test/lightbridge.unit.spec.ts @@ -595,8 +595,15 @@ describe('Asset Teleportation Tests', async () => { it('should withdraw ERC20 balance', async () => { const preSignerBalnce = await L2Boba.balanceOf(signerAddress) - const preBalance = await L2Boba.balanceOf(Proxy__Teleportation.address) - await expect(Proxy__Teleportation.withdrawBalance(L2Boba.address)) + let preBalance = await L2Boba.balanceOf(Proxy__Teleportation.address) + + const partialAmount = preBalance.div(3) + await expect(Proxy__Teleportation.withdrawBalance(L2Boba.address, partialAmount)) + .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') + .withArgs(L2Boba.address, signerAddress, partialAmount) + + preBalance = await L2Boba.balanceOf(Proxy__Teleportation.address) + await expect(Proxy__Teleportation.withdrawBalance(L2Boba.address, preBalance)) .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') .withArgs(L2Boba.address, signerAddress, preBalance) @@ -610,7 +617,7 @@ describe('Asset Teleportation Tests', async () => { it('should not withdraw ERC20 balance if caller is not owner', async () => { await expect( - Proxy__Teleportation.connect(signer2).withdrawBalance(L2Boba.address) + Proxy__Teleportation.connect(signer2).withdrawBalance(L2Boba.address, '1') ).to.be.revertedWith('Caller is not the owner') }) @@ -1250,11 +1257,22 @@ describe('Asset Teleportation Tests', async () => { it('should withdraw BOBA balance', async () => { const preSignerBalnce = await ethers.provider.getBalance(signerAddress) - const preBalance = await ethers.provider.getBalance( + let preBalance = await ethers.provider.getBalance( + Proxy__Teleportation.address + ) + + const partialAmount = preBalance.div(3) + await expect( + Proxy__Teleportation.withdrawBalance(ethers.constants.AddressZero, partialAmount) + ) + .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') + .withArgs(ethers.constants.AddressZero, signerAddress, partialAmount) + + preBalance = await ethers.provider.getBalance( Proxy__Teleportation.address ) await expect( - Proxy__Teleportation.withdrawBalance(ethers.constants.AddressZero) + Proxy__Teleportation.withdrawBalance(ethers.constants.AddressZero, preBalance) ) .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') .withArgs(ethers.constants.AddressZero, signerAddress, preBalance) @@ -1275,7 +1293,7 @@ describe('Asset Teleportation Tests', async () => { it('should not withdraw BOBA balance if caller is not owner', async () => { await expect( Proxy__Teleportation.connect(signer2).withdrawBalance( - ethers.constants.AddressZero + ethers.constants.AddressZero, '1' ) ).to.be.revertedWith('Caller is not the owner') }) From 8989b02713e34c3ea08d188910c1c79615f55166 Mon Sep 17 00:00:00 2001 From: wsdt Date: Tue, 23 Apr 2024 01:07:50 +0200 Subject: [PATCH 2/6] fix withdraw, tests --- contracts/LightBridge.sol | 8 ++++---- test/lightbridge.unit.spec.ts | 26 ++++++++++++++++++++------ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/contracts/LightBridge.sol b/contracts/LightBridge.sol index bd773fe..68d6893 100644 --- a/contracts/LightBridge.sol +++ b/contracts/LightBridge.sol @@ -400,15 +400,15 @@ contract LightBridge is PausableUpgradeable, MulticallUpgradeable { if (address(0) == _token) { uint256 _balance = address(this).balance; require(_balance >= _amount, "Too high"); - (bool sent,) = owner.call{gas: 2300, value: _balance}(""); + (bool sent,) = owner.call{gas: 2300, value: _amount}(""); require(sent, "Failed to send Ether"); - emit AssetBalanceWithdrawn(_token, owner, _balance); + emit AssetBalanceWithdrawn(_token, owner, _amount); } else { // no supportedToken check in case of generally lost tokens uint256 _balance = IERC20(_token).balanceOf(address(this)); require(_balance > _amount, "Too high"); - IERC20(_token).safeTransfer(owner, _balance); - emit AssetBalanceWithdrawn(_token, owner, _balance); + IERC20(_token).safeTransfer(owner, _amount); + emit AssetBalanceWithdrawn(_token, owner, _amount); } } diff --git a/test/lightbridge.unit.spec.ts b/test/lightbridge.unit.spec.ts index e90dbb7..383ac08 100644 --- a/test/lightbridge.unit.spec.ts +++ b/test/lightbridge.unit.spec.ts @@ -598,12 +598,16 @@ describe('Asset Teleportation Tests', async () => { let preBalance = await L2Boba.balanceOf(Proxy__Teleportation.address) const partialAmount = preBalance.div(3) - await expect(Proxy__Teleportation.withdrawBalance(L2Boba.address, partialAmount)) + await expect( + Proxy__Teleportation.withdrawBalance(L2Boba.address, partialAmount) + ) .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') .withArgs(L2Boba.address, signerAddress, partialAmount) preBalance = await L2Boba.balanceOf(Proxy__Teleportation.address) - await expect(Proxy__Teleportation.withdrawBalance(L2Boba.address, preBalance)) + await expect( + Proxy__Teleportation.withdrawBalance(L2Boba.address, preBalance) + ) .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') .withArgs(L2Boba.address, signerAddress, preBalance) @@ -617,7 +621,10 @@ describe('Asset Teleportation Tests', async () => { it('should not withdraw ERC20 balance if caller is not owner', async () => { await expect( - Proxy__Teleportation.connect(signer2).withdrawBalance(L2Boba.address, '1') + Proxy__Teleportation.connect(signer2).withdrawBalance( + L2Boba.address, + '1' + ) ).to.be.revertedWith('Caller is not the owner') }) @@ -1263,7 +1270,10 @@ describe('Asset Teleportation Tests', async () => { const partialAmount = preBalance.div(3) await expect( - Proxy__Teleportation.withdrawBalance(ethers.constants.AddressZero, partialAmount) + Proxy__Teleportation.withdrawBalance( + ethers.constants.AddressZero, + partialAmount + ) ) .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') .withArgs(ethers.constants.AddressZero, signerAddress, partialAmount) @@ -1272,7 +1282,10 @@ describe('Asset Teleportation Tests', async () => { Proxy__Teleportation.address ) await expect( - Proxy__Teleportation.withdrawBalance(ethers.constants.AddressZero, preBalance) + Proxy__Teleportation.withdrawBalance( + ethers.constants.AddressZero, + preBalance + ) ) .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') .withArgs(ethers.constants.AddressZero, signerAddress, preBalance) @@ -1293,7 +1306,8 @@ describe('Asset Teleportation Tests', async () => { it('should not withdraw BOBA balance if caller is not owner', async () => { await expect( Proxy__Teleportation.connect(signer2).withdrawBalance( - ethers.constants.AddressZero, '1' + ethers.constants.AddressZero, + '1' ) ).to.be.revertedWith('Caller is not the owner') }) From 54b8cdccab913138147b71fa7e95046f32bc75b5 Mon Sep 17 00:00:00 2001 From: wsdt Date: Tue, 23 Apr 2024 01:18:24 +0200 Subject: [PATCH 3/6] fix withdraw, tests --- contracts/LightBridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/LightBridge.sol b/contracts/LightBridge.sol index 68d6893..b2bcbb5 100644 --- a/contracts/LightBridge.sol +++ b/contracts/LightBridge.sol @@ -406,7 +406,7 @@ contract LightBridge is PausableUpgradeable, MulticallUpgradeable { } else { // no supportedToken check in case of generally lost tokens uint256 _balance = IERC20(_token).balanceOf(address(this)); - require(_balance > _amount, "Too high"); + require(_balance >= _amount, "Too high"); IERC20(_token).safeTransfer(owner, _amount); emit AssetBalanceWithdrawn(_token, owner, _amount); } From 82d9e920f7b9c370753d563912ee89873e71ee29 Mon Sep 17 00:00:00 2001 From: wsdt Date: Tue, 23 Apr 2024 01:27:48 +0200 Subject: [PATCH 4/6] fix withdraw, tests --- test/lightbridge.unit.spec.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/lightbridge.unit.spec.ts b/test/lightbridge.unit.spec.ts index 383ac08..1bde447 100644 --- a/test/lightbridge.unit.spec.ts +++ b/test/lightbridge.unit.spec.ts @@ -595,7 +595,7 @@ describe('Asset Teleportation Tests', async () => { it('should withdraw ERC20 balance', async () => { const preSignerBalnce = await L2Boba.balanceOf(signerAddress) - let preBalance = await L2Boba.balanceOf(Proxy__Teleportation.address) + const preBalance = await L2Boba.balanceOf(Proxy__Teleportation.address) const partialAmount = preBalance.div(3) await expect( @@ -604,12 +604,12 @@ describe('Asset Teleportation Tests', async () => { .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') .withArgs(L2Boba.address, signerAddress, partialAmount) - preBalance = await L2Boba.balanceOf(Proxy__Teleportation.address) + const newPreBalance = await L2Boba.balanceOf(Proxy__Teleportation.address) await expect( - Proxy__Teleportation.withdrawBalance(L2Boba.address, preBalance) + Proxy__Teleportation.withdrawBalance(L2Boba.address, newPreBalance) ) .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') - .withArgs(L2Boba.address, signerAddress, preBalance) + .withArgs(L2Boba.address, signerAddress, newPreBalance) const postBalance = await L2Boba.balanceOf(Proxy__Teleportation.address) const postSignerBalance = await L2Boba.balanceOf(signerAddress) @@ -1264,7 +1264,7 @@ describe('Asset Teleportation Tests', async () => { it('should withdraw BOBA balance', async () => { const preSignerBalnce = await ethers.provider.getBalance(signerAddress) - let preBalance = await ethers.provider.getBalance( + const preBalance = await ethers.provider.getBalance( Proxy__Teleportation.address ) @@ -1278,17 +1278,17 @@ describe('Asset Teleportation Tests', async () => { .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') .withArgs(ethers.constants.AddressZero, signerAddress, partialAmount) - preBalance = await ethers.provider.getBalance( + const newPreBalance = await ethers.provider.getBalance( Proxy__Teleportation.address ) await expect( Proxy__Teleportation.withdrawBalance( ethers.constants.AddressZero, - preBalance + newPreBalance ) ) .to.emit(Proxy__Teleportation, 'AssetBalanceWithdrawn') - .withArgs(ethers.constants.AddressZero, signerAddress, preBalance) + .withArgs(ethers.constants.AddressZero, signerAddress, newPreBalance) const postBalance = await ethers.provider.getBalance( Proxy__Teleportation.address From 112107ff7c30d10ee26a5cece3138ecab346cb80 Mon Sep 17 00:00:00 2001 From: wsdt Date: Tue, 23 Apr 2024 01:41:03 +0200 Subject: [PATCH 5/6] fix gas fee closeTo --- test/lightbridge.unit.spec.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/lightbridge.unit.spec.ts b/test/lightbridge.unit.spec.ts index 1bde447..d5c4cd2 100644 --- a/test/lightbridge.unit.spec.ts +++ b/test/lightbridge.unit.spec.ts @@ -1263,7 +1263,7 @@ describe('Asset Teleportation Tests', async () => { }) it('should withdraw BOBA balance', async () => { - const preSignerBalnce = await ethers.provider.getBalance(signerAddress) + const preSignerBalance = await ethers.provider.getBalance(signerAddress) const preBalance = await ethers.provider.getBalance( Proxy__Teleportation.address ) @@ -1297,8 +1297,9 @@ describe('Asset Teleportation Tests', async () => { signerAddress ) const gasFee = await getGasFeeFromLastestBlock(ethers.provider) - expect(preBalance.sub(postBalance)).to.be.eq( - postSignerBalance.sub(preSignerBalnce).add(gasFee) + expect(preBalance.sub(postBalance)).to.be.closeTo( + postSignerBalance.sub(preSignerBalance), + postSignerBalance.sub(preSignerBalance).add(gasFee), ) expect(postBalance.toString()).to.be.eq('0') }) From 55934c96fd5e2d07563e8d243c646ffef830a633 Mon Sep 17 00:00:00 2001 From: wsdt Date: Mon, 29 Apr 2024 18:49:31 +0200 Subject: [PATCH 6/6] chore: Cleanup --- contracts/LightBridge.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/LightBridge.sol b/contracts/LightBridge.sol index b2bcbb5..e59f343 100644 --- a/contracts/LightBridge.sol +++ b/contracts/LightBridge.sol @@ -397,19 +397,19 @@ contract LightBridge is PausableUpgradeable, MulticallUpgradeable { onlyOwner() onlyInitialized() { + require(_amount != 0, "Amount is 0"); if (address(0) == _token) { uint256 _balance = address(this).balance; require(_balance >= _amount, "Too high"); (bool sent,) = owner.call{gas: 2300, value: _amount}(""); require(sent, "Failed to send Ether"); - emit AssetBalanceWithdrawn(_token, owner, _amount); } else { // no supportedToken check in case of generally lost tokens uint256 _balance = IERC20(_token).balanceOf(address(this)); require(_balance >= _amount, "Too high"); IERC20(_token).safeTransfer(owner, _amount); - emit AssetBalanceWithdrawn(_token, owner, _amount); } + emit AssetBalanceWithdrawn(_token, owner, _amount); } /**