def test_approve(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) chain.wait.for_receipt( gntb.transact({ 'from': owner_addr }).approve(receiver_addr, 100)) with pytest.raises(TransactionFailed): gntb.transact({'from': owner_addr}).approve(receiver_addr, 200)
def test_close(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) pc = deploy_channels(chain, owner_addr, gntb) channel = prep_a_channel(chain, owner_addr, receiver_addr, gntb, pc) prep_a_channel(chain, owner_addr, receiver_addr, gntb, pc) # bad caller with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ 'from': receiver_addr }).close(channel)) assert pc.call().isLocked(channel) # unlock needed first with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ 'from': owner_addr }).close(channel)) topics = [owner_addr, receiver_addr] f_id = log_filter(chain, pc.address, "TimeLocked(address, address, bytes32)", topics) chain.wait.for_receipt(pc.transact({'from': owner_addr}).unlock(channel)) logs = get_logs(f_id) assert len(logs) == 1 achannel = logs[0]["data"] assert achannel == eth_utils.encode_hex(channel) # bad caller with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ 'from': receiver_addr }).close(channel)) f_id = log_filter(chain, pc.address, "Close(address, address, bytes32)", topics) # too early, still in close_delay period assert pc.call().isTimeLocked(channel) with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ 'from': owner_addr }).close(channel)) while pc.call().isTimeLocked(channel): chain.web3.testing.mine(1) # proper close chain.wait.for_receipt(pc.transact({'from': owner_addr}).close(channel)) logs = get_logs(f_id) assert len(logs) == 1 achannel = logs[0]["data"] assert achannel == eth_utils.encode_hex(channel) # can't withdraw from closed channel owner_priv = ethereum.tester.keys[9] V, ER, ES = sign_transfer(channel, owner_priv, receiver_addr, 10) with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ 'from': receiver_addr }).withdraw(channel, 10, V, ER, ES))
def test_batch_transfer_to_zero(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) addr = b'\0' * 20 vv = zpad(int_to_big_endian(1), 12) mix = vv + addr payments = [mix] assert len(mix) == 32 with pytest.raises(TransactionFailed): gntb.transact({'from': owner_addr}).batchTransfer(payments, 123)
def test_onTokenReceived(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) pc = deploy_channels(chain, owner_addr, gntb) channel = prep_a_channel(chain, owner_addr, receiver_addr, gntb, pc) with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ 'from': owner_addr }).onTokenReceived(owner_addr, 123, channel))
def test_onTokenReceived(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) pc = deploy_channels(chain, owner_addr, gntb) prep_a_channel(chain, owner_addr, receiver_addr, gntb, pc) with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({'from': owner_addr}).onTokenReceived(owner_addr, 123, receiver_addr))
def test_empty_gntb_conversions(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) gate_address = gntb.call().getGateAddress(owner_addr) assert gate_address gate_gnt_balance = gnt.call().balanceOf(gate_address) assert gate_gnt_balance == 0 with pytest.raises(TransactionFailed): gntb.transact({'from': owner_addr}).transferFromGate() gntb_balance = gntb.call().balanceOf(owner_addr) assert gntb_balance > 0 with pytest.raises(TransactionFailed): gntb.transact({'from': owner_addr}).withdraw(0)
def test_batch_transfer(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) eba0 = gntb.call().balanceOf(ethereum.tester.a0) eba1 = gntb.call().balanceOf(ethereum.tester.a1) eba2 = gntb.call().balanceOf(ethereum.tester.a2) eba3 = gntb.call().balanceOf(ethereum.tester.a3) eba4 = gntb.call().balanceOf(ethereum.tester.a4) payments, v = encode_payments([(1, 1), (2, 2), (3, 3), (4, 4)]) # This dict is used to count events for given block hash # There is a quirk that same events can appear many times during # "blockchain reorganization" they will have different block hash though. eventNoForHash = {} q = queue.Queue() # Callback is called on separate thread so one need a queue to collect data def onBatchEvent(arg, eventsQueue): eventsQueue.put(arg) cbk = functools.partial(onBatchEvent, eventsQueue=q) gntb.on('BatchTransfer', None, cbk) # Closure time has to be in past, requestor is making payments for # already made obligations closure_time = chain.web3.eth.getBlock('latest')['timestamp'] tx = chain.wait.for_receipt( gntb.transact({ 'from': ethereum.tester.a0 }).batchTransfer(payments, closure_time)) assert gntb.call().balanceOf(ethereum.tester.a1) == 1 + eba1 assert gntb.call().balanceOf(ethereum.tester.a2) == 2 + eba2 assert gntb.call().balanceOf(ethereum.tester.a3) == 3 + eba3 assert gntb.call().balanceOf(ethereum.tester.a4) == 4 + eba4 assert gntb.call().balanceOf(ethereum.tester.a0) == eba0 - v while not q.empty(): try: batchEvent = q.get() assert chain.web3.eth.getBlock( batchEvent['blockNumber'] )['timestamp'] >= batchEvent['args']['closureTime'] if batchEvent['blockHash'] in eventNoForHash.keys(): eventNoForHash[batchEvent['blockHash']] += 1 else: eventNoForHash = {batchEvent['blockHash']: 0} except: assert False for entry in eventNoForHash: assert eventNoForHash[entry] == 3
def test_close(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) pc = deploy_channels(chain, owner_addr, gntb) prep_a_channel(chain, owner_addr, receiver_addr, gntb, pc) # bad caller with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({'from': receiver_addr}).close(receiver_addr)) assert pc.call().isLocked(owner_addr, receiver_addr) # unlock needed first with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({'from': owner_addr}).close(receiver_addr)) topics = [owner_addr, receiver_addr] f_id = log_filter(chain, pc.address, "TimeLocked(address, address)", topics) chain.wait.for_receipt( pc.transact({'from': owner_addr}).unlock(receiver_addr)) logs = get_logs(f_id) assert len(logs) == 1 # achannel = logs[0]["data"] # assert achannel == eth_utils.encode_hex(channel) # bad caller with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({'from': receiver_addr}).close(receiver_addr)) f_id = log_filter(chain, pc.address, "Close(address, address)", topics) # too early, still in close_delay period assert pc.call().isTimeLocked(owner_addr, receiver_addr) with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({'from': owner_addr}).close(receiver_addr)) while pc.call().isTimeLocked(owner_addr, receiver_addr): chain.web3.testing.mine(1) # proper close chain.wait.for_receipt( pc.transact({'from': owner_addr}).close(receiver_addr)) logs = get_logs(f_id) assert len(logs) == 1 # achannel = logs[0]["data"] # assert achannel == eth_utils.encode_hex(channel) # can't withdraw from closed channel owner_priv = ethereum.tester.keys[9] V, ER, ES = sign_transfer(owner_priv, owner_addr, receiver_addr, 10) with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({'from': receiver_addr}).withdraw(owner_addr, 10, V, ER, ES))
def test_create_gnt(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) faucet, _ = chain.provider.get_or_deploy_contract( 'Faucet', deploy_args=[gnt.address]) assert gnt.call().balanceOf(faucet.address) == 0 chain.wait.for_receipt( gnt.transact({ 'from': encode_hex(ethereum.tester.a0) }).transfer(faucet.address, 1000 * utils.denoms.ether)) assert gnt.call().balanceOf(faucet.address) == 1000 * utils.denoms.ether key = sha3(to_string(11)) account = privtoaddr(key) ethereum.tester.accounts.append(account) ethereum.tester.keys.append(key) assert chain.web3.eth.getBalance(encode_hex(account)) == 0 previousA0 = chain.web3.eth.getBalance(encode_hex(ethereum.tester.a0)) assert previousA0 > utils.denoms.ether tx = Transaction( nonce=chain.web3.eth.getTransactionCount(ethereum.tester.a0), gasprice=chain.web3.eth.gasPrice, startgas=100000, to=encode_hex(account), value=utils.denoms.ether, data=b'', ) tx.sign(ethereum.tester.k0) raw_tx = rlp.encode(tx) raw_tx_hex = chain.web3.toHex(raw_tx) chain.web3.eth.sendRawTransaction(raw_tx_hex) assert gnt.call().balanceOf(faucet.address) == 1000 * utils.denoms.ether assert chain.web3.eth.getBalance(encode_hex(account)) == utils.denoms.ether assert gnt.call().decimals() == 18 assert gnt.call().balanceOf(encode_hex(account)) == 0 tx = chain.wait.for_receipt( faucet.transact({ 'from': encode_hex(account) }).create()) assert gnt.call().balanceOf( encode_hex(account)) == 1000 * utils.denoms.ether assert gnt.call().balanceOf(faucet.address) == 0
def test_batch_transfer(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) eba0 = gntb.call().balanceOf(ethereum.tester.a0) eba1 = gntb.call().balanceOf(ethereum.tester.a1) eba2 = gntb.call().balanceOf(ethereum.tester.a2) eba3 = gntb.call().balanceOf(ethereum.tester.a3) eba4 = gntb.call().balanceOf(ethereum.tester.a4) payments, v = encode_payments([(1, 1), (2, 2), (3, 3), (4, 4)]) # This dict is used to count events for given block hash # There is a quirk that same events can appear many times during # "blockchain reorganization" they will have different block hash though. eventNoForHash = {} q = queue.Queue() # Callback is called on separate thread so one need a queue to collect data def onBatchEvent(arg, eventsQueue): eventsQueue.put(arg) cbk = functools.partial(onBatchEvent, eventsQueue=q) gntb.on('BatchTransfer', None, cbk) # Closure time has to be in past, requestor is making payments for # already made obligations closure_time = chain.web3.eth.getBlock('latest')['timestamp'] tx = chain.wait.for_receipt(gntb.transact({'from': ethereum.tester.a0}).batchTransfer(payments, closure_time)) assert gntb.call().balanceOf(ethereum.tester.a1) == 1 + eba1 assert gntb.call().balanceOf(ethereum.tester.a2) == 2 + eba2 assert gntb.call().balanceOf(ethereum.tester.a3) == 3 + eba3 assert gntb.call().balanceOf(ethereum.tester.a4) == 4 + eba4 assert gntb.call().balanceOf(ethereum.tester.a0) == eba0 - v while not q.empty(): try: batchEvent = q.get() assert chain.web3.eth.getBlock(batchEvent['blockNumber'])['timestamp'] >= batchEvent['args']['closureTime'] if batchEvent['blockHash'] in eventNoForHash.keys(): eventNoForHash[batchEvent['blockHash']] += 1 else: eventNoForHash = {batchEvent['blockHash']: 0} except: assert False for entry in eventNoForHash: assert eventNoForHash[entry] == 3
def test_create_gnt(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) faucet, _ = chain.provider.get_or_deploy_contract('Faucet', deploy_args=[gnt.address]) assert gnt.call().balanceOf(faucet.address) == 0 chain.wait.for_receipt(gnt.transact({'from': encode_hex(ethereum.tester.a0)}).transfer( faucet.address, 1000 * utils.denoms.ether )) assert gnt.call().balanceOf(faucet.address) == 1000 * utils.denoms.ether key = sha3(to_string(11)) account = privtoaddr(key) ethereum.tester.accounts.append(account) ethereum.tester.keys.append(key) assert chain.web3.eth.getBalance(encode_hex(account)) == 0 previousA0 = chain.web3.eth.getBalance(encode_hex(ethereum.tester.a0)) assert previousA0 > utils.denoms.ether tx = Transaction( nonce=chain.web3.eth.getTransactionCount(ethereum.tester.a0), gasprice=chain.web3.eth.gasPrice, startgas=100000, to=encode_hex(account), value=utils.denoms.ether, data=b'', ) tx.sign(ethereum.tester.k0) raw_tx = rlp.encode(tx) raw_tx_hex = chain.web3.toHex(raw_tx) chain.web3.eth.sendRawTransaction(raw_tx_hex) assert gnt.call().balanceOf(faucet.address) == 1000 * utils.denoms.ether assert chain.web3.eth.getBalance(encode_hex(account)) == utils.denoms.ether assert gnt.call().decimals() == 18 assert gnt.call().balanceOf(encode_hex(account)) == 0 tx = chain.wait.for_receipt( faucet.transact({'from': encode_hex(account)}).create()) assert gnt.call().balanceOf(encode_hex(account)) == 1000 * utils.denoms.ether assert gnt.call().balanceOf(faucet.address) == 0
def test_forceClose(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) pc = deploy_channels(chain, owner_addr, gntb) channel = prep_a_channel(chain, owner_addr, receiver_addr, gntb, pc) # bad caller with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ 'from': owner_addr }).forceClose(channel)) topics = [owner_addr, receiver_addr] f_id = log_filter(chain, pc.address, "ForceClose(address, address, bytes32)", topics) # proper caller chain.wait.for_receipt( pc.transact({ 'from': receiver_addr }).forceClose(channel)) logs = get_logs(f_id) assert len(logs) == 1 achannel = logs[0]["data"] assert achannel == eth_utils.encode_hex(channel) # duplicate call with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ 'from': receiver_addr }).forceClose(channel)) # can't fund closed channel with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ 'from': owner_addr }).fund(channel, 100)) # can't withdraw from closed channel owner_priv = ethereum.tester.keys[9] V, ER, ES = sign_transfer(channel, owner_priv, receiver_addr, 10) with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ 'from': receiver_addr }).withdraw(channel, 10, V, ER, ES))
def test_withdraw(chain): owner_addr, _, gnt, gntb, cdep = mysetup(chain) owner_priv = ethereum.tester.keys[7] receiver_addr = tester.accounts[1] pc = deploy_channels(chain, owner_addr, gntb) channel = prep_a_channel(chain, owner_addr, receiver_addr, gntb, pc) def capacity(): dep = pc.call().getDeposited(channel) wit = pc.call().getWithdrawn(channel) return dep - wit def shared_capacity(): return gntb.call().balanceOf(pc.address) c_cap = capacity() sh_cap = shared_capacity() V, ER, ES = sign_transfer(channel, owner_priv, receiver_addr, 10) assert pc.call().isValidSig(channel, 10, V, ER, ES) # withdraw wrong amount with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ "from": receiver_addr }).withdraw(channel, 1000, V, ER, ES)) # withdraw wrong amount with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ "from": receiver_addr }).withdraw(channel, 5, V, ER, ES)) # use damaged signature ES1 = bytearray(ES) ES1[3] = (~ES1[3]) % 256 # bitwise not ES1 = bytes(ES1) with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ "from": receiver_addr }).withdraw(channel, 10, V, ER, ES1)) # successful withdrawal assert 10 <= shared_capacity() assert 10 <= capacity() assert pc.call().isValidSig(channel, 10, V, ER, ES) chain.wait.for_receipt( pc.transact({ "from": receiver_addr }).withdraw(channel, 10, V, ER, ES)) assert capacity() == c_cap - 10 assert shared_capacity() == sh_cap - 10 # reuse correctly signed cheque with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ "from": receiver_addr }).withdraw(channel, 10, V, ER, ES)) # try to double-spend by reversing order of applying cheques V, ER, ES = sign_transfer(channel, owner_priv, receiver_addr, 5) with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({ "from": receiver_addr }).withdraw(channel, 5, V, ER, ES)) # get 10 more V, ER, ES = sign_transfer(channel, owner_priv, receiver_addr, 20) chain.wait.for_receipt( pc.transact({ "from": receiver_addr }).withdraw(channel, 20, V, ER, ES)) assert capacity() == c_cap - 20 assert shared_capacity() == sh_cap - 20
def test_withdraw(chain): owner_addr, _, gnt, gntb, cdep = mysetup(chain) owner_priv = ethereum.tester.keys[7] receiver_addr = tester.accounts[1] pc = deploy_channels(chain, owner_addr, gntb) prep_a_channel(chain, owner_addr, receiver_addr, gntb, pc) def capacity(): dep = pc.call().getDeposited(owner_addr, receiver_addr) wit = pc.call().getWithdrawn(owner_addr, receiver_addr) return dep - wit def shared_capacity(): return gntb.call().balanceOf(pc.address) c_cap = capacity() sh_cap = shared_capacity() V, ER, ES = sign_transfer(owner_priv, owner_addr, receiver_addr, 10) assert pc.call().isValidSig(owner_addr, receiver_addr, 10, V, ER, ES) # withdraw wrong amount with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({"from": receiver_addr}).withdraw(owner_addr, 1000, V, ER, ES)) # withdraw wrong amount with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({"from": receiver_addr}).withdraw(owner_addr, 5, V, ER, ES)) # use damaged signature ES1 = bytearray(ES) ES1[3] = (~ES1[3]) % 256 # bitwise not ES1 = bytes(ES1) with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({"from": receiver_addr}).withdraw(owner_addr, 10, V, ER, ES1)) # successful withdrawal assert 10 <= shared_capacity() assert 10 <= capacity() assert pc.call().isValidSig(owner_addr, receiver_addr, 10, V, ER, ES) chain.wait.for_receipt( pc.transact({"from": receiver_addr}).withdraw(owner_addr, 10, V, ER, ES)) assert capacity() == c_cap - 10 assert shared_capacity() == sh_cap - 10 # reuse correctly signed cheque with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({"from": receiver_addr}).withdraw(owner_addr, 10, V, ER, ES)) # try to double-spend by reversing order of applying cheques V, ER, ES = sign_transfer(owner_priv, owner_addr, receiver_addr, 5) with pytest.raises(TransactionFailed): chain.wait.for_receipt( pc.transact({"from": receiver_addr}).withdraw(owner_addr, 5, V, ER, ES)) # get 10 more V, ER, ES = sign_transfer(owner_priv, owner_addr, receiver_addr, 20) chain.wait.for_receipt( pc.transact({"from": receiver_addr}).withdraw(owner_addr, 20, V, ER, ES)) assert capacity() == c_cap - 20 assert shared_capacity() == sh_cap - 20
def test_batch_transfer_to_self(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) addr = ethereum.tester.a1 payments, _ = encode_payments([(1, 1)]) with pytest.raises(TransactionFailed): gntb.transact({'from': addr}).batchTransfer(payments, 123)
def test_approve(chain): owner_addr, receiver_addr, gnt, gntb, cdep = mysetup(chain) chain.wait.for_receipt( gntb.transact({'from': owner_addr}).approve(receiver_addr, 100)) with pytest.raises(TransactionFailed): gntb.transact({'from': owner_addr}).approve(receiver_addr, 200)