Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .buildkite/steps/deploy-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,17 @@ export PROXY_URL=http://127.0.0.1:9090/solana

echo "Wait proxy..." && wait-for-proxy "$PROXY_URL"

export EVM_LOADER=$(docker exec proxy bash -c "cat evm_loader_id" | sed '/Program Id: \([0-9A-Za-z]\+\)/,${s//\1/;b};s/^.*$//;$q1')
export SOLANA_URL=$(docker exec solana bash -c 'echo "$SOLANA_URL"')

echo "EVM_LOADER" $EVM_LOADER
echo "SOLANA_URL" $SOLANA_URL

echo "Run proxy tests..."
docker run --rm -ti --network=host \
docker run --rm -ti --network=container:proxy \
-e PROXY_URL \
-e EVM_LOADER \
-e SOLANA_URL \
-e EXTRA_GAS=100000 \
--entrypoint ./proxy/deploy-test.sh \
${EXTRA_ARGS:-} \
Expand Down
25 changes: 21 additions & 4 deletions proxy/plugin/solana_rest_api_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,6 @@ def create_account_list_by_emulate(signer, client, ethTrx):
sender_ether = bytes.fromhex(ethTrx.sender())
add_keys_05 = []
trx = Transaction()
new_neon_token_acccounts = []

output_json = call_emulated(ethTrx.toAddress.hex(), sender_ether.hex(), ethTrx.callData.hex(), hex(ethTrx.value))
logger.debug("emulator returns: %s", json.dumps(output_json, indent=3))
Expand Down Expand Up @@ -858,7 +857,6 @@ def create_account_list_by_emulate(signer, client, ethTrx):

(create_trx, solana_address, token_address) = createEtherAccountTrx(client, address, evm_loader_id, signer, code_account)
trx.add(create_trx)
new_neon_token_acccounts.append(token_address)

if address == sender_ether and NEW_USER_AIRDROP_AMOUNT > 0:
trx.add(transfer2(Transfer2Params(
Expand All @@ -878,8 +876,8 @@ def create_account_list_by_emulate(signer, client, ethTrx):
for token_account in output_json["token_accounts"]:
add_keys_05.append(AccountMeta(pubkey=PublicKey(token_account["key"]), is_signer=False, is_writable=True))

if token_account["new"] and (PublicKey(token_account["key"]) not in new_neon_token_acccounts):
trx.add(create_associated_token_account(signer.public_key(), PublicKey(token_account["owner"]), PublicKey(token_account["mint"])))
if token_account["new"]:
trx.add(createERC20TokenAccountTrx(signer, token_account))

for account_meta in output_json["solana_accounts"]:
add_keys_05.append(AccountMeta(pubkey=PublicKey(account_meta["pubkey"]), is_signer=account_meta["is_signer"], is_writable=account_meta["is_writable"]))
Expand Down Expand Up @@ -1041,6 +1039,25 @@ def createEtherAccountTrx(client, ether, evm_loader_id, signer, code_acc=None):
]))
return (trx, sol, associated_token)

def createERC20TokenAccountTrx(signer, token_info):
trx = Transaction()
trx.add(TransactionInstruction(
program_id=evm_loader_id,
data=bytes.fromhex('0F'),
keys=[
AccountMeta(pubkey=signer.public_key(), is_signer=True, is_writable=True),
AccountMeta(pubkey=PublicKey(token_info["key"]), is_signer=False, is_writable=True),
AccountMeta(pubkey=PublicKey(token_info["owner"]), is_signer=False, is_writable=True),
AccountMeta(pubkey=PublicKey(token_info["contract"]), is_signer=False, is_writable=True),
AccountMeta(pubkey=PublicKey(token_info["mint"]), is_signer=False, is_writable=True),
AccountMeta(pubkey=system, is_signer=False, is_writable=False),
AccountMeta(pubkey=TOKEN_PROGRAM_ID, is_signer=False, is_writable=False),
AccountMeta(pubkey=rentid, is_signer=False, is_writable=False),
]))

return trx



def write_trx_to_holder_account(signer, client, holder, ethTrx):
msg = ethTrx.signature() + len(ethTrx.unsigned_msg()).to_bytes(8, byteorder="little") + ethTrx.unsigned_msg()
Expand Down
59 changes: 52 additions & 7 deletions proxy/test_erc20_wrapper_contract.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
## File: test_erc20_wrapper_contract.py
## Integration test for the Neon ERC20 Wrapper contract.

from time import sleep
import unittest
import os
from solana.rpc.commitment import Confirmed, Recent
from solana.rpc.types import TxOpts
from web3 import Web3
from solcx import install_solc
from spl.token.client import Token as SplToken
from spl.token.constants import TOKEN_PROGRAM_ID
from solana.rpc.api import Client as SolanaClient
from solana.account import Account as SolanaAccount
from solana.publickey import PublicKey

from proxy.plugin.solana_rest_api_tools import createERC20TokenAccountTrx, createEtherAccountTrx

# install_solc(version='latest')
install_solc(version='0.7.6')
from solcx import compile_source

EXTRA_GAS = int(os.environ.get("EXTRA_GAS", "100000"))
proxy_url = os.environ.get('PROXY_URL', 'http://localhost:9090/solana')
proxy_url = os.environ.get('PROXY_URL', 'http://127.0.0.1:9090/solana')
solana_url = os.environ.get("SOLANA_URL", "http://127.0.0.1:8899")
evm_loader_id = PublicKey(os.environ.get("EVM_LOADER"))
proxy = Web3(Web3.HTTPProvider(proxy_url))
admin = proxy.eth.account.create('issues/neonlabsorg/proxy-model.py/197/admin')
user = proxy.eth.account.create('issues/neonlabsorg/proxy-model.py/197/user')
Expand All @@ -20,10 +32,6 @@
NAME = 'NEON'
SYMBOL = 'NEO'

# token_mint::id = "HPsV9Deocecw3GeZv1FkAPNCBRfuVyfw9MMwjwRe1xaU" in Base58
# Convert Base58 to hex number:
TOKEN_MINT = bytes.fromhex('f396da383e57418540f8caa598584f49a3b50d256f75cb6d94d101681d6d9d21')

# Standard interface of ERC20 contract to generate ABI for wrapper
ERC20_INTERFACE_SOURCE = '''
pragma solidity >=0.7.0;
Expand Down Expand Up @@ -100,7 +108,31 @@ def setUpClass(cls):
print('admin.address:', admin.address)
print('user.key:', user.key.hex())
print('user.address:', user.address)

cls.create_token_mint(cls)
cls.deploy_erc20_wrapper_contract(cls)
cls.create_token_accounts(cls)


def create_token_mint(self):
self.solana_client = SolanaClient(solana_url)

self.solana_account = SolanaAccount()
self.solana_client.request_airdrop(self.solana_account.public_key(), 1000_000_000_000, Confirmed)

while True:
balance = self.solana_client.get_balance(self.solana_account.public_key(), Confirmed)["result"]["value"]
if balance > 0:
break
sleep(1)

self.token = SplToken.create_mint(
self.solana_client,
self.solana_account,
self.solana_account.public_key(),
9,
TOKEN_PROGRAM_ID,
)

def deploy_erc20_wrapper_contract(self):
compiled_interface = compile_source(ERC20_INTERFACE_SOURCE)
Expand All @@ -114,15 +146,28 @@ def deploy_erc20_wrapper_contract(self):
erc20 = proxy.eth.contract(abi=self.wrapper['abi'], bytecode=wrapper_interface['bin'])
nonce = proxy.eth.get_transaction_count(proxy.eth.default_account)
tx = {'nonce': nonce}
tx_constructor = erc20.constructor(NAME, SYMBOL, TOKEN_MINT).buildTransaction(tx)
tx_constructor = erc20.constructor(NAME, SYMBOL, bytes(self.token.pubkey)).buildTransaction(tx)
tx_deploy = proxy.eth.account.sign_transaction(tx_constructor, admin.key)
#print('tx_deploy:', tx_deploy)
tx_deploy_hash = proxy.eth.send_raw_transaction(tx_deploy.rawTransaction)
print('tx_deploy_hash:', tx_deploy_hash.hex())
tx_deploy_receipt = proxy.eth.wait_for_transaction_receipt(tx_deploy_hash)
print('tx_deploy_receipt:', tx_deploy_receipt)
print('deploy status:', tx_deploy_receipt.status)
self.contract_address= tx_deploy_receipt.contractAddress
self.contract_address = tx_deploy_receipt.contractAddress

def create_token_accounts(self):
contract_address_bytes = bytes.fromhex(self.contract_address[2:])
contract_address_solana = PublicKey.find_program_address([b"\1", contract_address_bytes], evm_loader_id)[0]

admin_address_bytes = bytes.fromhex(admin.address[2:])
admin_address_solana = PublicKey.find_program_address([b"\1", admin_address_bytes], evm_loader_id)[0]

admin_token_seeds = [ b"\1", b"ERC20Balance", bytes(self.token.pubkey), contract_address_bytes, admin_address_bytes ]
admin_token_key = PublicKey.find_program_address(admin_token_seeds, evm_loader_id)[0]
admin_token_info = { "key": admin_token_key, "owner": admin_address_solana, "contract": contract_address_solana, "mint": self.token.pubkey }
self.solana_client.send_transaction(createERC20TokenAccountTrx(self.solana_account, admin_token_info), self.solana_account, opts=TxOpts(skip_preflight=True, skip_confirmation=False))
self.token.mint_to(admin_token_key, self.solana_account, 10_000_000_000_000, opts=TxOpts(skip_preflight=True, skip_confirmation=False))

def test_erc20_name(self):
erc20 = proxy.eth.contract(address=self.contract_address, abi=self.wrapper['abi'])
Expand Down