Payment forwarder that sends every incoming payment to a receiver address and logs both ether and token movements with the contract as an explicit party.
Historical Significance
Both events name this contract as a party rather than only the sender and receiver. For an operator running many forwarding addresses, that makes a single log stream enough to attribute a payment to the address it arrived at, without needing to join against a deployment list. Leaving the token sweep open to any caller is a deliberate trade: it costs nothing to let a stranger pay gas to move funds that can only ever go to the receiver.
Key Facts
Description
The payable fallback transfers the full incoming value to the receiver held in the first storage slot and emits ethTransfer carrying the sender, this contract, the receiver and the amount. transferToken does the same job for an ERC20: it reads the contract's own balance, and if there is anything to move it transfers the whole balance to the receiver and emits tokenTransfer with the token address, this contract, the receiver and the amount.
updateReceiver is the only privileged function, gated on a second stored owner address, and it carries the revert reason only can be called by owner. transferToken itself is deliberately unguarded, so anyone can push a stranded token balance onward.
Source Verified
Byzantium Era
First Metropolis hard fork. Added zk-SNARK precompiles, REVERT opcode, and staticcall.
Bytecode Overview
Verified Source Available
This contract has verified source code.
View Verification ProofShow source code (Solidity)
// Submitted by EthereumHistory (ethereumhistory.com)
pragma solidity ^0.4.24;
contract ERC20 {
function balanceOf(address _owner) public view returns (uint256);
function transfer(address _to, uint256 _value) public;
}
contract Forwarder {
address receiver;
address owner;
event ethTransfer(address from, address to, address receiver, uint256 amount);
event tokenTransfer(address token, address from, address receiver, uint256 amount);
function () public payable {
receiver.transfer(msg.value);
emit ethTransfer(msg.sender, address(this), receiver, msg.value);
}
function updateReceiver(address _receiver) public {
require(msg.sender == owner, "only can be called by owner");
receiver = _receiver;
}
function transferToken(address _token) public {
ERC20 token = ERC20(_token);
address self = address(this);
uint256 bal = token.balanceOf(self);
if (bal <= 0) {
return;
}
token.transfer(receiver, bal);
emit tokenTransfer(_token, self, receiver, bal);
}
}