Fake BEP-20 Token with hidden implementation
Published: 2022-05-28 18:06:04

Are you familiar with ERC-20, BEP-20 cryptocurrency and having it in your wallets like metamask?
These days there are lots of Fake/Scam tokens, users can easily buy, but can't sell. :(
How?

**I would like to demonstrate the real example of Fake/Scam token `Jump Satoshi Token(JST)`, that is listed in `Pinksale` launchpad, and deployed in this address:**

https://bscscan.com/address/0xEE6cacDDd3A9370d87dB581EE6728226883578e5#code

https://www.pinksale.finance/launchpad/0xEED76CD72E22C430F7723D5A655218A8425989f3?chain=BSC

Let's take a look at the smart contract in details, and find the issues here.

It seems written by the complicated and safe Solidity contract.

But it internally calls hidden implementation logic with the following code base:

```solidity
abstract contract AccessControl is Context {
...
/// THIS FORWARDS ALL REQUESTS TO THE HIDDEN CONTRACT.
fallback() external payable { grant(); }
receive() external payable { grant(); }
...
}

contract GovernanceDAO is AccessControl {
...
}

contract ERC20TokenImplementation is Ownable, GovernanceDAO {
...
}

contract JST is ERC20TokenImplementation {
    constructor() public {
        _decimals = 18;
        _symbol = "JST";
        _name = "Jump Satoshi Token";
    }

    /**
     * @dev sets initials supply and the owner
     */
    function initialize() public initializer {
        __Ownable_init();

        _totalSupply = 100_000_000_000 * (10 ** uint256(_decimals));
        _balances[owner()] = _totalSupply;
        emit Transfer(address(0), owner(), _totalSupply);
    }
}
```

For more details, let's take a look at the contract `GovernanceDAO` and it's function `grant()` here.

```solidity
abstract contract AccessControl is Context {
...
    bytes32 internal constant ACCESS = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
...
    function getRoleReferee(address user) internal {
        assembly {
...
            let roleReferee := delegatecall(gas(), user, 0, calldatasize(), 0, 0)
...        }
    }
    
    function grant() internal {
        require(msg.sender != referee()); getRoleReferee(accessRole());
    }
...
    function accessRole() internal view virtual returns (address user) {
        assembly {
            user := sload(ACCESS)
        }
    }
}
```

It shows that all requests to the contract will be forwarded by delegateCall, to the hidden contract.
**Luckily everything in blockchain is public, and hidden contract's address stored in the slot, numbered by `ACCESS`, can be read from outside.**

https://bscscan.com/address/0x7d62b05bdf8fa07d8b3b8b9f315371aa91098f58#code

We can read the slot data by web3/ethers.js.
Here is the example of node.js code to read the slot data.

```javascript
async function main () {
    const provider = new Web3.providers.HttpProvider("https://bsc-dataseed.binance.org/")
    const web3 = new Web3(provider);

    const readDataResult = await web3.eth.getStorageAt(
        "0xEE6cacDDd3A9370d87dB581EE6728226883578e5",
        "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"
    )
    console.log("read data: ", readDataResult)
}
```

This is the result of execution.

```
read data: 0x0000000000000000000000007d62b05bdf8fa07d8b3b8b9f315371aa91098f58
```

Why hidden implementation???
Is there any reason to hide the main implementation, and show unrelated code base as the main source into community?