Wallet

This wallet contract is capable of receiving, holding and sending Ether as well as tokens that comply with one of the following standards:

Implementation in Vyper

Deploying

The wallet contract accesses the ERC1820Registry contract in its constructor. It is therefore necessary that the ERC1820Registry contract exists on the (test) network to where the wallet contract gets deployed.

In migrations/1_initial_migration.js a check is performed to determine if the ERC1820Registry contract exists - if it doesn't it is deployed.

wallet.vy
# Author: Sören Steiger, twitter.com/ssteiger_
# License: MIT
contract ERC1820Registry:
def setInterfaceImplementer(
_addr: address,
_interfaceHash: bytes32,
_implementer: address
): modifying
contract ERC20Token:
def transfer(
_to: address,
_value: uint256
) -> bool: modifying
contract ERC721Token:
def safeTransferFrom(
_from: address,
_to: address,
_tokenId: uint256,
_data: bytes[256]
): modifying
contract ERC777Token:
def send(
_to: address,
_amount: uint256,
_data: bytes[256]
): modifying
ETHReceived: event({
_from: address,
_amount: wei_value
})
ETHSent: event({
_to: address,
_amount: uint256
})
# TODO:
#ERC20Received: event({
#})
ERC20Sent: event({
_token: address,
_to: address,
_amount: uint256
})
ERC721Received: event({
_token: address,
_from: address,
_tokenId: uint256,
_data: bytes32
})
ERC721Sent: event({
_token: address,
_from: address,
_to: address,
_tokenId: uint256,
_data: bytes[256]
})
ERC777Received: event({
_operator: indexed(address),
_from: indexed(address),
_to: indexed(address),
_amount: uint256,
_data: bytes[256],
_operatorData: bytes[256]
})
ERC777Sent: event({
_operator: indexed(address),
_from: indexed(address),
_to: indexed(address),
_amount: uint256,
_data: bytes[256],
_operatorData: bytes[256]
})
erc1820Registry: ERC1820Registry
erc1820RegistryAddress: constant(address) = 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24
owner: public(address)
@public
def __init__():
self.owner = msg.sender
self.erc1820Registry = ERC1820Registry(erc1820RegistryAddress)
self.erc1820Registry.setInterfaceImplementer(self, keccak256("ERC777TokensRecipient"), self)
self.erc1820Registry.setInterfaceImplementer(self, keccak256("ERC777TokensSender"), self)
# ----- ETH -----
@public
@payable
def __default__():
log.ETHReceived(msg.sender, msg.value)
@public
def sendETH(
_to: address,
_amount: uint256
):
assert msg.sender == self.owner
send(_to, _amount)
log.ETHSent(_to, _amount)
# ----- ERC20 -----
@public
def sendERC20(
_token: address,
_to: address,
_amount: uint256
):
assert msg.sender == self.owner
ERC20Token(_token).transfer(_to, _amount)
log.ERC20Sent(_token, _to, _amount)
#@public
#def onERC20Received():
# ----- ERC721 -----
@public
def sendERC721(
_token: address,
_to: address,
_tokenId: uint256,
_data: bytes[256]=""
):
assert msg.sender == self.owner
ERC721Token(_token).safeTransferFrom(self, _to, _tokenId, _data)
log.ERC721Sent(_token, self, _to, _tokenId, _data)
@public
def onERC721Received(
_token: address,
_from: address,
_tokenId: uint256,
_data: bytes32
) -> bytes32:
log.ERC721Received(_token, _from, _tokenId, _data)
# TODO: need to return bytes4
return keccak256("onERC721Received(address,address,uint256,bytes)")
# ----- ERC777 -----
@public
def sendERC777(
_token: address,
_to: address,
_amount: uint256,
_data: bytes[256]=""
):
assert msg.sender == self.owner
ERC777Token(_token).send(_to, _amount, _data)
@public
def tokensToSend(
_operator: address,
_from: address,
_to: address,
_amount: uint256,
_data: bytes[256],
_operatorData: bytes[256]
):
log.ERC777Sent(_operator, _from, _to, _amount, _data, _operatorData)
@public
def tokensReceived(
_operator: address,
_from: address,
_to: address,
_amount: uint256,
_data: bytes[256],
_operatorData: bytes[256]
):
log.ERC777Received(_operator, _from, _to, _amount, _data, _operatorData)