Skip to content

Commit

Permalink
Rework test_neon_faucet.py with predeployed ERC20 tokens (#744)
Browse files Browse the repository at this point in the history
Adjust test_neon_faucet.py to new faucet features
  • Loading branch information
vakond authored and afalaleev committed Apr 26, 2022
1 parent 44e4ea5 commit 6979116
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 148 deletions.
10 changes: 7 additions & 3 deletions proxy/docker-compose-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,14 @@ services:
environment:
FAUCET_RPC_PORT: 3333
FAUCET_RPC_ALLOWED_ORIGINS: '["http://airdropper"]'
FAUCET_WEB3_ENABLE: 'false'
FAUCET_WEB3_ENABLE: 'true'
WEB3_RPC_URL: http://solana:8899
WEB3_PRIVATE_KEY: 0x4deacb079b4714c38f39508aa8900039f2721ed8686835d43347ba9267da767b
NEON_ERC20_TOKENS: '["0xB521b9F3484deF53545F276F1DAA50ef0Ca82E2d", "0x8a2a66CA0E5D491A001957edD45A6350bC76D708", "0x914782059DC42d4E590aeFCfdbF004B2EcBB9fAA", "0x7A7510b9b18241C788a7aAE8299D1fA6010D8128"]'
NEON_ERC20_MAX_AMOUNT: 1000
FAUCET_SOLANA_ENABLE: 'true'
SOLANA_URL: 'http://solana:8899'
NEON_OPERATOR_KEYFILE: '/root/.config/solana/id.json'
SOLANA_URL: http://solana:8899
NEON_OPERATOR_KEYFILE: /root/.config/solana/id.json
NEON_ETH_MAX_AMOUNT: 1000
TEST_FAUCET_INIT_NEON_BALANCE: 100000
hostname: faucet
Expand Down
175 changes: 30 additions & 145 deletions proxy/testing/test_neon_faucet.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,170 +3,28 @@

import unittest
import os
import io
import time
import subprocess
import requests
from web3 import Web3
from solcx import compile_source

from proxy.testing.testing_helpers import request_airdrop

issue = 'https://github.com/neonlabsorg/neon-evm/issues/166'
proxy_url = os.environ.get('PROXY_URL', 'http://localhost:9090/solana')
proxy = Web3(Web3.HTTPProvider(proxy_url))
admin = proxy.eth.account.create(issue + '/admin')
user = proxy.eth.account.create(issue + '/user')
proxy.eth.default_account = admin.address
request_airdrop(admin.address)

ERC20_CONTRACT_SOURCE = '''
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0;
// ----------------------------------------------------------------------------
// Safe maths
// ----------------------------------------------------------------------------
contract SafeMath {
function safeAdd(uint a, uint b) public pure returns (uint c) {
c = a + b;
require(c >= a);
}
function safeSub(uint a, uint b) public pure returns (uint c) {
require(b <= a);
c = a - b;
}
}
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
// ----------------------------------------------------------------------------
abstract contract ERC20Interface {
function totalSupply() virtual public view returns (uint);
function balanceOf(address tokenOwner) virtual public view returns (uint balance);
function allowance(address tokenOwner, address spender) virtual public view returns (uint remaining);
function transfer(address to, uint tokens) virtual public returns (bool success);
function approve(address spender, uint tokens) virtual public returns (bool success);
function transferFrom(address from, address to, uint tokens) virtual public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals
// assisted token transfers
// ----------------------------------------------------------------------------
contract TestToken is ERC20Interface, SafeMath {
string public symbol;
string public name;
uint8 public decimals;
uint public _totalSupply;
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
constructor() {
symbol = "TST";
name = "TestToken";
decimals = 18;
_totalSupply = 100000000000000000000000000000000000000000;
balances[msg.sender] = _totalSupply;
emit Transfer(address(0), msg.sender, _totalSupply);
}
// ------------------------------------------------------------------------
// Total supply
// ------------------------------------------------------------------------
function totalSupply() public override view returns (uint) {
return _totalSupply - balances[address(0)];
}
// ------------------------------------------------------------------------
// Get the token balance for account tokenOwner
// ------------------------------------------------------------------------
function balanceOf(address tokenOwner) public override view returns (uint balance) {
return balances[tokenOwner];
}
// ------------------------------------------------------------------------
// Transfer the balance from token owner's account to receiver account
// - Owner's account must have sufficient balance to transfer
// - 0 value transfers are allowed
// ------------------------------------------------------------------------
function transfer(address receiver, uint tokens) public override returns (bool success) {
balances[msg.sender] = safeSub(balances[msg.sender], tokens);
balances[receiver] = safeAdd(balances[receiver], tokens);
emit Transfer(msg.sender, receiver, tokens);
return true;
}
// ------------------------------------------------------------------------
// Token owner can approve for spender to transferFrom(...) tokens
// from the token owner's account
//
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
// recommends that there are no checks for the approval double-spend attack
// as this should be implemented in user interfaces
// ------------------------------------------------------------------------
function approve(address spender, uint tokens) public override returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
return true;
}
// ------------------------------------------------------------------------
// Transfer tokens from sender account to receiver account
//
// The calling account must already have sufficient tokens approve(...)-d
// for spending from sender account and
// - From account must have sufficient balance to transfer
// - Spender must have sufficient allowance to transfer
// - 0 value transfers are allowed
// ------------------------------------------------------------------------
function transferFrom(address sender, address receiver, uint tokens) public override returns (bool success) {
balances[sender] = safeSub(balances[sender], tokens);
allowed[sender][msg.sender] = safeSub(allowed[sender][msg.sender], tokens);
balances[receiver] = safeAdd(balances[receiver], tokens);
emit Transfer(sender, receiver, tokens);
return true;
}
// ------------------------------------------------------------------------
// Returns the amount of tokens approved by the owner that can be
// transferred to the spender's account
// ------------------------------------------------------------------------
function allowance(address tokenOwner, address spender) public override view returns (uint remaining) {
return allowed[tokenOwner][spender];
}
}
'''

class Test_Neon_Faucet(unittest.TestCase):
@classmethod
def setUpClass(cls):
print('\n\n' + issue)
cls.compile_erc20_contract(cls)
cls.token_a = cls.deploy_erc20_token(cls, 'A')
cls.token_b = cls.deploy_erc20_token(cls, 'B')

def compile_erc20_contract(self):
print('Compiling ERC20 contract...')
compiled_contract = compile_source(ERC20_CONTRACT_SOURCE)
contract_id, contract_interface = compiled_contract.popitem()
self.contract = contract_interface

def deploy_erc20_token(self, name):
print('Deploying ERC20 token...')
erc20 = proxy.eth.contract(abi=self.contract['abi'], bytecode=self.contract['bin'])
nonce = proxy.eth.get_transaction_count(proxy.eth.default_account)
tx = {'nonce': nonce}
tx_constructor = erc20.constructor().buildTransaction(tx)
tx_deploy = proxy.eth.account.sign_transaction(tx_constructor, admin.key)
tx_deploy_hash = proxy.eth.send_raw_transaction(tx_deploy.rawTransaction)
tx_deploy_receipt = proxy.eth.wait_for_transaction_receipt(tx_deploy_hash)
print('Token', name, '=', tx_deploy_receipt.contractAddress)
return tx_deploy_receipt.contractAddress

# @unittest.skip("a.i.")
def test_neon_faucet_00_ping(self):
print()
url = '{}/request_ping'.format(os.environ['FAUCET_URL'])
print(url)
data = '{"ping": "Hello"}'
r = requests.post(url, data=data)
r = requests.get(url, data=data)
if not r.ok:
print('Response:', r.status_code)
assert(r.ok)
Expand All @@ -175,7 +33,7 @@ def test_neon_faucet_00_ping(self):
def test_neon_faucet_01_version(self):
print()
url = '{}/request_version'.format(os.environ['FAUCET_URL'])
r = requests.post(url)
r = requests.get(url)
if not r.ok:
print('Response:', r.status_code)
assert(r.ok)
Expand Down Expand Up @@ -214,8 +72,35 @@ def test_neon_faucet_03_neon(self):
print('NEO balance difference:', balance_after - balance_before)
self.assertEqual(balance_after - balance_before, 1000000000000000000)

# @unittest.skip("a.i.")
def test_neon_faucet_04_erc20_list(self):
print()
url = '{}/request_erc20_list'.format(os.environ['FAUCET_URL'])
r = requests.get(url)
if not r.ok:
print('Response:', r.status_code)
assert(r.ok)
self.assertEqual(r.text, '["0xB521b9F3484deF53545F276F1DAA50ef0Ca82E2d","0x8a2a66CA0E5D491A001957edD45A6350bC76D708","0x914782059DC42d4E590aeFCfdbF004B2EcBB9fAA","0x7A7510b9b18241C788a7aAE8299D1fA6010D8128"]')

@unittest.skip("a.i.")
def test_neon_faucet_06_erc20_single(self):
print()
url = '{}/request_erc20'.format(os.environ['FAUCET_URL'])
token = '0xB521b9F3484deF53545F276F1DAA50ef0Ca82E2d'
before = self.get_token_balance(token, user.address)
print('token A balance before:', before)
data = '{"wallet": "' + user.address + '", "token_addr": "' + token + '", "amount": 1}'
print('data:', data)
r = requests.post(url, data=data)
if not r.ok:
print('Response:', r.status_code)
assert(r.ok)
after = self.get_token_balance(token, user.address)
print('token A balance after:', after)
self.assertEqual(after - before, 1000000000000000000)

@unittest.skip("a.i.")
def test_neon_faucet_04_erc20(self):
def test_neon_faucet_05_erc20_all(self):
print()
url = '{}/request_erc20'.format(os.environ['FAUCET_URL'])
a_before = self.get_token_balance(self.token_a, user.address)
Expand Down

0 comments on commit 6979116

Please sign in to comment.