From 0ad4bb4e3f898b41c2ca5521a1469a8879088179 Mon Sep 17 00:00:00 2001 From: Owen Hu <103096885+owen-reorg@users.noreply.github.com> Date: Tue, 21 Nov 2023 22:23:17 +0800 Subject: [PATCH] fix: withdraw bep20 error --- .github/workflows/build.yaml | 4 +- contracts/src/L2StandardBridgeBot.sol | 6 +++ contracts/test/L2StandardBridgeBot.t.sol | 50 ++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 contracts/test/L2StandardBridgeBot.t.sol diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 24b7144..f0deb2e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -24,7 +24,7 @@ jobs: - name: Make build-go run: make build-go - 'build-solidity': + 'build-solidity and test': name: make build-solidity runs-on: ubuntu-latest steps: @@ -38,4 +38,4 @@ jobs: uses: foundry-rs/foundry-toolchain@v1 - name: Make build-solidity - run: cd contracts && forge build + run: cd contracts && forge build && forge test diff --git a/contracts/src/L2StandardBridgeBot.sol b/contracts/src/L2StandardBridgeBot.sol index 9e0d2ae..043c4f1 100644 --- a/contracts/src/L2StandardBridgeBot.sol +++ b/contracts/src/L2StandardBridgeBot.sol @@ -1,6 +1,7 @@ pragma solidity 0.8.20; import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; +import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; interface IL2StandardBridge { function withdrawTo( @@ -45,6 +46,11 @@ contract L2StandardBridgeBot is Ownable { } else { require(msg.value == delegationFee, "BEP20 withdrawal: msg.value does not equal to delegationFee"); + IERC20 l2Token = IERC20(_l2Token); + bool approveSuccess = l2Token.approve(L2_STANDARD_BRIDGE_ADDRESS, _amount + l2Token.allowance(address(this), L2_STANDARD_BRIDGE_ADDRESS)); + require(approveSuccess, "BEP20 withdrawal: approve failed"); + bool transferSuccess = l2Token.transferFrom(msg.sender, address(this), _amount); + require(transferSuccess, "BEP20 withdrawal: transferFrom failed"); L2_STANDARD_BRIDGE.withdrawTo{value: 0}(_l2Token, _to, _amount, _minGasLimit, _extraData); } diff --git a/contracts/test/L2StandardBridgeBot.t.sol b/contracts/test/L2StandardBridgeBot.t.sol new file mode 100644 index 0000000..57e313b --- /dev/null +++ b/contracts/test/L2StandardBridgeBot.t.sol @@ -0,0 +1,50 @@ +pragma solidity 0.8.20; + +import "forge-std/Test.sol"; +import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import { Ownable } from "openzeppelin-contracts/contracts/access/Ownable.sol"; +import "../src/L2StandardBridgeBot.sol"; + +contract L2StandardBridgeBotTest is Test { + L2StandardBridgeBot bot; + uint256 opbnbMainnetFork; + address deployer = address(0x1234); + address usdt = 0xCF712f20c85421d00EAa1B6F6545AaEEb4492B75; + address user = 0x3977f9B1F4912a783B44aBa813dA388AC73a1428; + uint withdrawFee = 10000; + address constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000; + + function setUp() public { + opbnbMainnetFork = vm.createFork("https://opbnb-testnet-rpc.bnbchain.org"); + vm.selectFork(opbnbMainnetFork); + vm.rollFork(opbnbMainnetFork, 7125821); + bot = new L2StandardBridgeBot(payable(deployer), withdrawFee); + } + + function test_RevertSetDelegationFeeNotOwner() public { + vm.expectRevert(); + bot.setDelegationFee(100); + } + + function test_setDelegationFee() public { + vm.prank(deployer); + bot.setDelegationFee(100); + assertEq(bot.delegationFee(), 100); + } + + function test_withdrawBNB() public { + vm.prank(user); + uint amount = 100; + bot.withdrawTo{value: withdrawFee + amount}(LEGACY_ERC20_ETH, user, amount, 200000, ""); + } + + function test_ERC20() public { + uint amount = 100; + uint balanceBefore = IERC20(usdt).balanceOf(user); + console2.log("balanceBefore", balanceBefore); + vm.prank(user); + IERC20(usdt).approve(address(bot), amount); + vm.prank(user); + bot.withdrawTo{value: withdrawFee}(usdt, user, amount, 200000, ""); + } +}