Skip to content

Code

BridgeBase.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { console } from "forge-std/console.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
interface IBUSDT is IERC20 {
function mint(address _to, uint256 _amount) external;
function burn(address _from, uint256 _amount) external;
}
contract BridgeETH is Ownable {
uint256 public balance;
address public tokenAddress;
event Burn(address indexed burner, uint amount);
mapping(address => uint256) public pendingBalance;
constructor(address _tokenAddress) Ownable(msg.sender) {
tokenAddress = _tokenAddress;
}
function burn(IBUSDT _tokenAddress, uint256 _amount) public {
require(address(_tokenAddress) == tokenAddress);
_tokenAddress.burn(msg.sender, _amount);
emit Burn(msg.sender, _amount);
}
function withdraw(IBUSDT _tokenAddress, uint256 _amount) public {
require(pendingBalance[msg.sender] >= _amount);
pendingBalance[msg.sender] -= _amount;
_tokenAddress.mint(msg.sender, _amount);
}
function burnedOnOppositeChain(address userAccount, uint256 _amount) public onlyOwner {
pendingBalance[userAccount] += _amount;
}
}

BridgeETH.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { console } from "forge-std/console.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
contract BridgeETH is Ownable {
uint256 public balance;
address public tokenAddress;
event Deposit(address indexed depositor, uint amount);
mapping(address => uint256) public pendingBalance;
constructor(address _tokenAddress) Ownable(msg.sender) {
tokenAddress = _tokenAddress;
}
function deposit(IERC20 _tokenAddress, uint256 _amount) public {
require(address(_tokenAddress) == tokenAddress);
require(_tokenAddress.allowance(msg.sender, address(this)) >= _amount);
require(_tokenAddress.transferFrom(msg.sender, address(this), _amount));
emit Deposit(msg.sender, _amount);
}
function withdraw(IERC20 _tokenAddress, uint256 _amount) public {
require(pendingBalance[msg.sender] >= _amount);
pendingBalance[msg.sender] -= _amount;
_tokenAddress.transfer(msg.sender, _amount);
}
function burnedOnOppositeChain(address userAccount, uint256 _amount) public onlyOwner {
pendingBalance[userAccount] += _amount;
}
}

BUSDT.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { console } from "forge-std/console.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
contract BUSDT is ERC20, Ownable {
constructor() ERC20("USDT", "USDT") Ownable(msg.sender) {
}
function mint(address _to, uint256 _amount) public onlyOwner {
_mint(_to, _amount);
}
function burn(address _from, uint256 _amount) public onlyOwner {
_burn(_from, _amount);
}
}

USDT.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { console } from "forge-std/console.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
contract USDT is ERC20, Ownable {
constructor() ERC20("USDT", "USDT") Ownable(msg.sender) {
}
function mint(address _to, uint256 _amount) public onlyOwner {
_mint(_to, _amount);
}
}

Assignment

Find the vulnerability in here