Search code examples
ethereumsolidity

solidity: call contract function from another contract with the same msg.sender


I have a function that needs to call the transfer method on another contract. I want the transfer method to be called from the address of the original caller and not the contract. Is it possible?

This is the code:

function buyGameBundle(string calldata id) external nonReentrant {
    structGameBundles  memory currentItem = _gameBundles[id];
    require(currentItem.exists == true, "bundle does not exists");
    require(currentItem.totalSupply > 0, "there are no more bundles left");
    if (currentItem.cost > 0) {
        erc20.transfer(_feesAccount, currentItem.cost);
    }
    currentItem.totalSupply = currentItem.totalSupply.sub(1);
    _gameBundles[id] = currentItem;
    emit BuyGameBundle(_msgSender(), id, currentItem.cost);
}

Solution

  • erc20.transfer(_feesAccount, currentItem.cost);
    

    Your current code performs a message call (docs). Another name for the same thing is an EVM call. It uses storage of the target contract, and the msg.sender is your contract (not the original transaction sender).

    If you want the msg.sender to be the original transaction sender (the user), you need to use a delegatecall (docs). But... a delegatecall uses storage of the caller (your contract; not the called contract), so it's mostly useful for proxy contracts.


    For security reasons, it's not possible to execute a function in a target contract, using the target contract storage and msg.sender of the original sender.

    If it were possible, you could theoretically steal tokens from anyone who doesn't/can't verify your contract source code. Example:

    usdt.transfer(attacker, usdt.balanceOf(victim));
    weth.transfer(attacker, weth.balanceOf(victim));
    // ...