0

Basically, I want to setup a very simple token bridge try to bridge some custom tokens between BSC testnet & Goerli testnet. For BSC testnet, I created 2 solidity code: TokenBSC.sol & BridgeBSC.sol; for Goerli testnet, I created 2 solidity code: TokenEth.sol & BridgeEth.sol; My first task is to try to test most of the functions to make sure they are working. Here's a brief description of my contracts and their main tasks, along with some information about the major failure issues:

TokenBsc.sol

  • Description: TokenBsc.sol is a Solidity smart contract representing a token on the Binance Smart Chain (BSC). It follows the ERC-20 standard and provides functions for minting, approving, transferring, burning, and locking tokens.
  • Main Task: The main task of TokenBsc.sol is to manage token balances and allow users to perform various token-related operations on the BSC.

BridgeBsc.sol

  • Description: BridgeBsc.sol is a Solidity smart contract that interacts with TokenBsc.sol and facilitates the bridging of tokens from Binance Smart Chain (BSC) to another blockchain. It provides functions for locking tokens on BSC, minting equivalent tokens on the other blockchain, burning tokens on BSC, and releasing tokens on the other blockchain.
  • Main Task: The primary task of BridgeBsc.sol is to ensure the secure transfer of tokens between BSC and another blockchain, maintaining a 1:1 pegging ratio.

TokenEth.sol

  • Description: TokenEth.sol is a Solidity smart contract representing a token on the Ethereum blockchain. Similar to TokenBsc.sol, it follows the ERC-20 standard and provides functions for minting, approving, transferring, burning, and locking tokens. However, the total supply is set to 0, indicating that tokens need to be minted.
  • Main Task: TokenEth.sol manages token balances and allows users to perform various token-related operations on the Ethereum blockchain.

BridgeEth.sol

  • Description: BridgeEth.sol interacts with TokenEth.sol and facilitates the bridging of tokens from the Ethereum blockchain to another blockchain. It provides functions for locking tokens on Ethereum, minting equivalent tokens on the other blockchain, burning tokens on Ethereum, and releasing tokens on the other blockchain.
  • Main Task: BridgeEth.sol ensures the secure transfer of tokens between Ethereum and another blockchain, maintaining a 1:1 pegging ratio.

Major Failure Issues:

  • TransferFrom Issue in BridgeBsc.sol: The transferFrom function in BridgeBsc.sol may not work as expected. It attempts to transfer tokens from the sender's address (from) to the contract's address (address(this)). However, this may not always succeed, leading to a potential failure in locking tokens.

  • TransferFrom Issue in TokenBsc.sol: Similarly, the transferFrom function in TokenBsc.sol may encounter issues when allowing the contract to transfer tokens on behalf of the owner. If the allowance is not set correctly, this function may fail to transfer tokens.

  • Locking Tokens Issue: In the lock function of BridgeBsc.sol, if the token.transferFrom operation fails, it will trigger a revert, causing the transaction to fail. This could be due to insufficient allowance or other issues with the transferFrom operation.

These issues need to be thoroughly reviewed and debugged to ensure the proper functioning of the bridge and token contracts. It's essential to check allowances, balances, and the order of operations to prevent failures and maintain the integrity of the token bridge. Collaboration with the Solidity community can be valuable in addressing these issues. Issue Description: The issue involves the failure of the transferFrom function in the BridgeBsc.sol contract when attempting to lock tokens. Despite the approve function working correctly, the transferFrom operation fails.

Technical Details:

  1. Smart Contracts Involved:

    • BridgeBsc.sol (Bridge Smart Contract)

      • Address: 0xDb12e1741242B3703b3077EDC23d22cA056a65C1 (Shortened as: 0xDb)
    • Metamask Wallet (You)

      • BSC Testnet Address: 0x56073fb7c776abF41A09fB0831fB8fcA53f582A2 (Shortened as: 0x56)
  2. Relevant Smart Contract Code (BridgeBsc.sol):

    • approve function works as expected.
    • transferFrom function encounters an issue.
    // This function works correctly
    function approve(address spender, uint256 value) external returns (bool) {
        require(msg.sender == admin, 'Only admin can call this function');
        uint256 approveAmount = value * (10 ** uint256(decimals));
        allowance[msg.sender][spender] = approveAmount;
        emit Approval(msg.sender, spender, approveAmount);
        return true;
    }
    
    // This function encounters an issue
    function transferFrom(address from, address to, uint256 value) external returns (bool) {
        uint256 transferFromAmount = value * (10 ** uint256(decimals));
        balanceOf[from] -= transferFromAmount;
        balanceOf[to] += transferFromAmount;
        allowance[from][msg.sender] -= transferFromAmount;
        emit Transfer(from, to, transferFromAmount);
        return true;
    }
    
  3. Transaction Details:

    • Transaction Hash: 0xae24e691095410d3b00de25f3b1e4828fb16331ca25f49e0b373b260b4a42753
    • Status: Fail
    • Block: 33226893
    • Timestamp: 14 secs ago (Sep-10-2023 08:25:47 PM +UTC)
    • Method: Lock
    • From: 0x56073fb7c776abF41A09fB0831fB8fcA53f582A2
    • To: 0xDb12e1741242B3703b3077EDC23d22cA056a65C1
    • Value: 0 BNB ($0.00)
    • Transaction Fee: 0.000183215 BNB ($0.04)
    • Gas Price: 5 Gwei (0.000000005 BNB)
  4. Input Details (Failed transferFrom Function Call):

    • from Address: 0x56 (Your Metamask wallet address)
    • to Address: 0xDb (BridgeBsc.sol Smart Contract Address)
    • value (Amount to Transfer): 100
  5. Description of the Issue:

    • While calling the transferFrom function to lock 100 tokens, the transaction failed with a status of "Fail."
    • The approve function was successfully executed earlier, indicating that you have admin rights.
    • The specific cause of the failure in the transferFrom function needs further investigation, as it should have deducted tokens from your wallet (0x56) and transferred them to the BridgeBsc.sol contract (0xDb). However, the transfer failed.

By presenting these technical details, you can share your issue on a Solidity forum, allowing other community members to better understand the problem and provide assistance in resolving the issue.

Related code in TokenBsc.sol: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;

contract TokenBsc { string public name; string public symbol; uint8 public decimals; uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; mapping(address => uint256) public lockTimes; address public admin;

event Approval(address indexed owner, address indexed spender, uint256 value);
event LockTokens(address indexed account, uint256 lockTime); 
event Transfer(address indexed from, address indexed to, uint256 value);

constructor() {
    name = 'BSC Token';
    symbol = 'BSCToken';
    decimals = 8;
    totalSupply = 21000000 * (10 ** uint256(decimals));
    balanceOf[msg.sender] = totalSupply;
    admin = msg.sender;
}

function mint(address to, uint256 amount) external {
    require(msg.sender == admin, 'Only admin can call this function');
    require(to != address(0), 'Invalid address');
    require(amount > 0, 'Amount must be greater than zero');
    uint256 mintAmount = amount * (10 ** uint256(decimals));
    totalSupply += mintAmount;
    balanceOf[to] += mintAmount;
    emit Transfer(address(0), to, mintAmount);
}

function approve(address spender, uint256 value) external returns (bool) {
    require(msg.sender == admin, 'Only admin can call this function');
    uint256 approveAmount = value * (10 ** uint256(decimals));
    allowance[msg.sender][spender] = approveAmount;
    emit Approval(msg.sender, spender, approveAmount);
    return true;
}

function burn(uint256 amount) external {
    require(msg.sender == admin, 'Only admin can call this function');
    uint256 burnAmount = amount * (10 ** uint256(decimals));
    require(balanceOf[msg.sender] >= burnAmount, "Insufficient balance");
    balanceOf[msg.sender] -= burnAmount;
    totalSupply -= burnAmount;
    emit Transfer(msg.sender, address(0), burnAmount);
}

function transfer(address to, uint256 value) external returns (bool) {
    uint256 transferAmount = value * (10 ** uint256(decimals));
    balanceOf[msg.sender] -= transferAmount;
    balanceOf[to] += transferAmount;
    emit Transfer(msg.sender, to, transferAmount);
    return true;
}

function transferFrom(address from, address to, uint256 value) external returns (bool) {
    uint256 transferFromAmount = value * (10 ** uint256(decimals));
    balanceOf[from] -= transferFromAmount;
    balanceOf[to] += transferFromAmount;
    allowance[from][msg.sender] -= transferFromAmount;
    emit Transfer(from, to, transferFromAmount);
    return true;
}

function updateAdmin(address newAdmin) external {
    require(msg.sender == admin, 'only admin');
    admin = newAdmin;
}

function lockTokens() external {
    uint256 maxLockTime = ~uint256(0);
    lockTimes[msg.sender] = maxLockTime;
    emit LockTokens(msg.sender, maxLockTime);
}

}

Related code in BridgeBsc.sol: // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;

import './TokenBsc.sol'; interface ERC20 { function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); }

contract BridgeBsc { address private _contractTokenBase;

constructor(address _token, address _nativeTokenOwner, uint8 _tokenDecimals, address _tokenBase) {
    admin = msg.sender;
    token = ERC20(_token);
    nativeTokenOwner = _nativeTokenOwner;
    tokenDecimals = _tokenDecimals;
    fees = 1;
    _contractTokenBase = _tokenBase; 
}

ERC20 public token;
address public admin;
address public nativeTokenOwner;
uint8 public tokenDecimals;
uint private fees;
TokenBsc public tokenBase;

enum Step { Lock, Mint, Burn, Release }

event AdminMismatch(address indexed adminAddress, address indexed sender);
event BridgeContractApproved(address indexed owner, address indexed bridgeContract, uint256 allowance);
event DebugLockedAmount(string description, uint256 amount);  
event DepositedNativeTokens(address indexed sender, uint256 amount);
event MismatchSignature(bytes userSignature, bytes soliditySignature);
event ReceivedEther(address indexed sender, uint256 amount);
event TokensLocked(address indexed from, uint256 amount, uint256 timestamp, uint nonce, bytes signature);
event TokensReleased(address indexed to, uint256 amount, uint256 timestamp);
event Transfer(address from, address to, uint amount, uint date, uint nonce, bytes signature, Step indexed step);

mapping(address => mapping(uint => bool)) public processedNonces;
mapping(address => bool) public hasPaidFees;

function getAdmin() public view returns (address) {
    return admin;
}

function lock(address from, uint amount) external {
    uint lockingAmount = amount * (10 ** uint256(tokenDecimals));
    bool success = token.transferFrom(from, address(this), lockingAmount);
    if (!success) {
        revert("Transfer failed");
    }
}

..... => My current major task is how to make the 'lock' function working. Any suggesitons are appreciated!

1
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer.
    – Community Bot
    Sep 10, 2023 at 23:36

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.