If we deploy the contract B, and pass the contract B address to the contract A. When call the contract B function from the contract A, inside the contract B function, the msg.sender is the "address of contract A", not external account original calls from the contract A.
Here is the example:
pragma solidity ^0.4.18;
contract metaCoin {
mapping (address => uint) public balances;
address[] public addresses;
function metaCoin() {
balances[msg.sender] = 10000;
addresses.push( msg.sender );
}
function getBalance(address _addr) public view returns (uint) {
return balances[_addr];
}
function sendToken(address receiver, uint amount) returns(bool successful, address _caller){
if (balances[msg.sender] < amount) return (false, msg.sender);
balances[msg.sender] -= amount;
balances[receiver] += amount;
addresses.push( receiver );
return (false, msg.sender);
}
}
contract coinCaller{
function sendCoin(address coinContractAddress, address receiver, uint amount) public returns (address) {
metaCoin m = metaCoin(coinContractAddress);
var (status, addr) = m.sendToken(receiver, amount);
return addr;
}
}
Step 1. Using the account, 0x1328500533b017449698300A868fA24eaC1D7486
to deploy metaCoin contract at the address, 0x9628a8814b1b83c67a974f23af8dfd16fea49ae9
Step 2. Use the same account to deploy coinCaller
contract at the address 0xd8d5b5f968f119531a941a05682bbbb154d367c0
, then call,
coinCaller.sendCoin("0x9628a8814b1b83c67a974f23af8dfd16fea49ae9", "_any_account_addr_", 88)
This function should have transferred the balance from 0x1328500533b017449698300A868fA24eaC1D7486
to _any_account_addr_
with 88. But, it doesn't perform like that. The issue is that in metaCoin.sendToken()
the msg.sender
is coinCaller
contract address, 0xd8d5b5f968f119531a941a05682bbbb154d367c0
.
This is documented in the Solidity documentation as the "sender of the message (current call)", which is the coinCaller
contract in this call.
Is there a way to work around this to have the external account address of coinCaller.sendCoin()
?
Best Answer
It's not possible or even desirable.
You're trying to achieve an arrangement where
contract coinCaller
can spend ETH that belongs to other accounts.You should be treating
coinCaller
more like an escrow account or an ATM. It has it's own balance.Not possible:
coinCaller
instructs Alice's wallet to send ETH to Bob.Is Possible: Alice sends Alice's ETH to
coinCaller
with instructions to forward or hold for Bob.It might help to think of the contract as a sort of programmable vending machine.
Hope it helps.