EXMO token deposit wallet from October 2017: rejects ether, and lets its owner move any ERC20 out with a raw call built from the string transfer(address,uint256).
Historical Significance
EXMO was one of the main exchanges for Russian-speaking users in the 2017 cycle, and this is the address its customers were given for token deposits. The raw call built from a selector string is a period habit worth noticing: it predates abi.encodeWithSignature and was the usual way to talk to a token without trusting its return value, a problem that became widely known in 2018 when stricter return-data checks broke contracts calling tokens that did not follow the standard exactly.
Key Facts
Description
Each copy of this contract is a token deposit address for the EXMO exchange. This one, from 11 October 2017, was deployed by and is owned by the account Etherscan labels Exmo 7; the bulk of later copies came from a deployer account funded by the address labelled Exmo 4.
Ownership uses an early OpenZeppelin Claimable pattern. transferOwnership only nominates a pendingOwner, who must then call claimOwnership to take control. In this version the pending-owner check is a plain if, so a call from anyone else does nothing rather than reverting. The fallback function reverts, so ether sent to the address bounces.
The only operational function is transfer(address token, address to, uint256 value), restricted to the owner. Rather than calling through a token interface, it hashes the string transfer(address,uint256) at runtime, takes the first four bytes as the selector and issues a low-level call to the token, returning whether the call succeeded. A low-level call does not care whether the token returns a boolean, so the wallet works with both standard tokens and older ones that return nothing. The source was compiled with solc 0.4.17 with the optimizer on at 200 runs. The runtime code matches the deployed bytecode; only the trailing swarm metadata hash differs, because the EthereumHistory attribution comment changes the source text. Sourcify records this as a partial match and Etherscan shows it as verified.
Source Verified
Spurious Dragon Era
Continued DoS protection. State trie clearing.
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.11;
contract Ownable {
address public owner;
function Ownable() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
}
contract Claimable is Ownable {
address public pendingOwner;
modifier onlyPendingOwner() {
if (msg.sender == pendingOwner)
_;
}
function transferOwnership(address newOwner) onlyOwner {
pendingOwner = newOwner;
}
function claimOwnership() onlyPendingOwner {
owner = pendingOwner;
pendingOwner = 0x0;
}
}
contract ExmoDepositWallet is Claimable {
function () {
revert();
}
function transfer(address _token, address _to, uint256 _value) onlyOwner returns (bool) {
return _token.call(bytes4(sha3("transfer(address,uint256)")), _to, _value);
}
}