8

I am writing a smart contract which will contain an escrow service. The escrow is to be a smart contract and eventually I want to use it to transfer meta tokens from the escrows address to another user. The issue I have is that I want to be able to transfer from the escrow but have a modifier which allows only the escrow contract itself to call. I have tried to make a modifier which only allows "this" (referring to the contract address) to make the call but that doesn't work.

If a contract internally calls another function how can I have it that only the contract itself can call the function and have the transfer happen. Msg.sender doesn't seem to accommodate for this.

My Code:

  modifier contractOnly(){
    address contractAddress = this;
    if(msg.sender != contractAddress) throw; _
}

and the transfer function (which needs the modifier to prevent anyone from calling the function and taking all the tokens from the escrow)

  function transfer(address from, address to, uint amount)
    contractOnly returns (uint) {
    balances[from] -= amount;
    balances[to] += amount;
    return balances[from];
}
1
  • 2
    Why cant you specify the function as internal? Is anyone calling that function or only a function in the same contract ?
    – dragosb
    Commented Aug 8, 2016 at 7:41

1 Answer 1

5

You should be able to write your function like this using the internal modifier which is built into solidity.

function transfer(address from, address to, uint amount) internal returns (uint) {
    balances[from] -= amount;
    balances[to] += amount;
    return balances[from];
}

This will mean that the transfer function will only be callable from within the function bodies of the other functions in this contract. Conversely the transfer function will not be callable from from any other contract.

The modifier you provided will work if the the contract actually calls itself (rather than just internally invoking the function).

contract MyInterface {
    modifier contractOnly(){
        address contractAddress = this;
        if(msg.sender != contractAddress) throw; _
    }
    function transfer(address from, address to, uint amount) contractOnly returns (uint);
}

contract TheContract is MyInterface {
    function transfer(address from, address to, uint amount) contractOnly returns (uint) {
        ...
    }

    function thisWillWork(address from, address to, uint amount) {
        MyInterface(address(this)).transfer(from, to, amount);
    }

    function thisWillFail(address from, address to, uint amount) {
        transfer(from, to, amount);
    }
}

In this example, the thisWillWork function calls the transfer function as an internal transaction, meaning a transaction between two contracts. As it turns out, it is merely transacting with itself, but it is doing so as an external call. In this case the msg.sender value becomes address(this) because the call is happening in a transaction initiated by the contract itself.

The thisWillFail function uses an internal call style meaning that it doesn't produce an internal transaction, but instead just calls the transfer function's code within the current running transaction using a JUMPDEST. In this case, the msg.sender value is preserved as the original caller because the call is not happening in a new transaction, but in the context of the current transaction.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.