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()
?
coinCaller
an exploitable.