There is no way in solidity to check if an address is a contract. One of the goals of Ethereum is for humans and smart contracts to both be treated equally.
https://stackoverflow.com/a/37670490/7218912
有时候确实有需要向智能合约转账:
但是大多数 smart contract 的 token 是不能转出的,只要合约里没写转出的逻辑,就不能转出。以太坊将智能合约看做是独立的个体,没人知道它的私钥,给不支持转出的智能合约转 token 就等于销毁了。! n# q' a6 q8 j& J; ?
当我们要转账时,会转到交易方的地址,不会闲着没事给智能合约转 token。但是这种事情仍然会发生,不断有人给 EOSTokenContract 转 EOS(见下图),EOSTokenContract 账户下现在有 154,834 EOS,价值 $1,176,738.4(价格 $7.6)。类似的,QtumTokenContract 账户下现在有 22,293 QTUM,价值 $158,280.3(价格 $7.1)。
这些 token 都都都都销毁了 (⊙?⊙)
Dexaran 认识到了这个问题,
4 C( c' v' t/ U1 X P+ H, \: j
Contracts that are not designed to work with tokens must reject incoming token transactions. Otherwise, each token becomes a potential token trap.
ERC20 token standard issues.(google docs)+ o3 ? u3 s: R! W8 O# C( ]3 _6 q
! e) E, N0 m6 E2 |$ J3 q/ a
并在 github 创建了一个 issue。
tokenFallback 函数,当转账到不能转出的智能合约地址时,将自动取消。6 y% J' Q: D, A2 ^) a( ]; a/ \" b
contract ERC223 {/ x) e2 t3 d" O. ?
function transfer(address to, uint value, bytes data) {
uint codeLength;8 H; {2 K$ O: g- l1 p2 b8 |
assembly {$ i, z+ e7 f F9 Y7 J7 G: e
codeLength := extcodesize(_to)6 {- d& ?$ l/ c$ r
} y# K# k% t( `
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
if(codeLength>0) {
// Require proper transaction handling.% ^% L1 ~6 Q, y5 `1 M
ERC223Receiver receiver = ERC223Receiver(_to);0 a7 Q3 ]8 \( s$ z
receiver.tokenFallback(msg.sender, _value, _data);+ Q- F, @9 U$ I! y6 i5 Q
}. i, b' h9 p2 Y u/ z
}0 ?% g/ t: N! @' i; v
}
【todo】:代码解释9 f% X# ~' C* z: |" S2 P
The biggest change is that ERC223 no longer allow token to be transferred to a contract that does not allow token to be withdrawn.
https://medium.com/cryptomover/what-are-erc20-and-erc223-tokens-307badcca5a



