Skip to content

Commit

Permalink
add helper scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
sskeirik committed Dec 11, 2024
1 parent 7095d45 commit d3f7068
Show file tree
Hide file tree
Showing 2 changed files with 303 additions and 0 deletions.
76 changes: 76 additions & 0 deletions scripts/deploy_contract.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/bash
# Example usage: ./deploy_contract.sh --contract-hex-path ./misc/registry.hex --private-key-path ./misc/private_key.txt --http-provider-url http://localhost:8545

# Function to display usage
usage() {
echo "Usage: $0 --contract-hex-path <path_to_contract_hex> --private-key-path <path_to_private_key> [--http-provider-url <http_provider_url>]"
exit 1
}

# Default HTTP provider URL
HTTP_PROVIDER="http://localhost:8545"

# Parse named arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
--contract-hex-path) CONTRACT_HEX_PATH="$2"; shift ;;
--private-key-path) PRIVATE_KEY_PATH="$2"; shift ;;
--http-provider-url) HTTP_PROVIDER="$2"; shift ;;
*) usage ;;
esac
shift
done

if [ -z "$CONTRACT_HEX_PATH" ]; then
usage
fi

# Read the private key from the file
PRIVATE_KEY=$(cat "$PRIVATE_KEY_PATH")

# Get the block number at the start of the script
BLOCK_NUMBER=$(cast block-number --rpc-url $HTTP_PROVIDER)
echo "Block number at start of script: $BLOCK_NUMBER"

# Get the sender address using the private key
SENDER_ADDRESS=$(cast wallet address --private-key $PRIVATE_KEY)
echo "Sender address: $SENDER_ADDRESS"

# Get the balance of the sender address
BALANCE=$(cast balance $SENDER_ADDRESS --rpc-url $HTTP_PROVIDER)
echo "Balance at start of script: $BALANCE"

# Read or compile the contract code
if [ -n "$CONTRACT_HEX_PATH" ]; then
# Read the contract code from the hex file
CONTRACT_CODE=$(cat "$CONTRACT_HEX_PATH" | tr -d '\n')
fi

# Prepend 0x to the contract code
CONTRACT_CODE="0x$CONTRACT_CODE"

# Deploy the contract
RECEIPT=$(cast send --private-key $PRIVATE_KEY --rpc-url $HTTP_PROVIDER --create $CONTRACT_CODE)
TX_HASH=$(echo "$RECEIPT" | grep 'transactionHash' | awk '{print $2}')
CONTRACT_ADDRESS=$(echo "$RECEIPT" | grep 'contractAddress' | awk '{print $2}')
echo "Transaction hash: $TX_HASH"

# Wait for the transaction to be mined
while true; do
RECEIPT=$(cast tx $TX_HASH --rpc-url $HTTP_PROVIDER)
if [ "$RECEIPT" != "null" ]; then
break
fi
sleep 1
done

# Get the block number at the end of the script
BLOCK_NUMBER=$(cast block-number --rpc-url $HTTP_PROVIDER)
echo "Block number at end of script: $BLOCK_NUMBER"

# Get the balance of the sender address
BALANCE=$(cast balance $SENDER_ADDRESS --rpc-url $HTTP_PROVIDER)
echo "Balance at end of script: $BALANCE"

# Echo the contract address
echo "Contract address: $CONTRACT_ADDRESS"
227 changes: 227 additions & 0 deletions scripts/ulm_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import os
import unittest

from eth_abi import decode, encode
from web3 import Web3
from web3.middleware import SignAndSendRawMiddlewareBuilder

class ulm_client:
"""Python interface to ULM"""

def setUp(self):
"""Set up test environment with web3 connection and account details"""
# Initialize web3 connection
self.rpc_url = os.getenv("RPC_URL")
self.web3 = Web3(Web3.HTTPProvider(self.rpc_url))

# Set up test account
self.test_account_private_key = os.getenv("TEST_ACCOUNT_PRIVATE_KEY")
self.test_account = self.web3.eth.account.from_key(
self.test_account_private_key
)
self.test_account_address = self.test_account.address

# Get contract addresses from environment
self.registry_address = os.getenv("REGISTRY_ADDRESS")
self.wbtc_address = os.getenv("WBTC_ADDRESS")
self.pi2_address = os.getenv("PI2_ADDRESS")
self.usdc_address = os.getenv("USDC_ADDRESS")
self.weth_address = os.getenv("WETH_ADDRESS")

# Add middleware to automatically sign transactions
self.web3.middleware_onion.inject(
SignAndSendRawMiddlewareBuilder.build(self.test_account), layer=0
)

def function_selector(self, function_signature):
"""Calculate function selector from signature
Args:
function_signature: String of function name and parameters
Returns:
bytes: First 4 bytes of keccak hash of function signature
"""
return self.web3.keccak(text=function_signature)[:4]

def mint_token(self, token_address):
# Mint
mint_selector = self.function_selector("mint(address,uint256)")
mint_data = encode(
["address", "uint256"],
[self.test_account_address, 1000000000000000000000000],
) # 1,000,000 tokens
mint_tx = self.web3.eth.send_transaction(
{
"from": self.test_account_address,
"to": token_address,
"data": mint_selector + mint_data,
}
)
mint_tx_receipt = self.web3.eth.wait_for_transaction_receipt(mint_tx)
self.assertEqual(mint_tx_receipt["status"], 1)

# Verify balance
get_token_balance_selector = self.function_selector("balanceOf(address)")
get_token_balance_data = encode(["address"], [self.test_account_address])
get_token_balance_result = self.web3.eth.call(
{
"to": token_address,
"data": get_token_balance_selector + get_token_balance_data,
}
)
token_a_balance = int.from_bytes(get_token_balance_result, "big")

self.assertEqual(token_a_balance, 1000000000000000000000000)

def approve_token(self, token_address):
"""Test approving spending of tokens"""
# Approve token A
approve_selector = self.function_selector("approve(address,uint256)")
approve_data = encode(
["address", "uint256"], [token_address, 500000000000000000000000]
) # 500,000 tokens
approve_token_tx = self.web3.eth.send_transaction(
{
"from": self.test_account_address,
"to": token_address,
"data": approve_selector + approve_data,
}
)
approve_token_tx_receipt = self.web3.eth.wait_for_transaction_receipt(
approve_token_tx
)
self.assertEqual(approve_token_tx_receipt["status"], 1)

# Verify token A allowance
allowance_selector = self.function_selector("allowance(address,address)")
allowance_token_data = encode(
["address", "address"], [self.test_account_address, token_address]
)
allowance_token_result = self.web3.eth.call(
{
"to": token_address,
"data": allowance_selector + allowance_token_data,
}
)
token_allowance = int.from_bytes(allowance_token_result, "big")
self.assertEqual(token_allowance, 500000000000000000000000)

def check_token_identity(
self, token_address, expected_name, expected_decimals, expected_symbol
):
"""Read token identity"""
token_identity_selector = self.function_selector("name()")
token_identity_data = encode([], [])
token_identity_result = self.web3.eth.call(
{
"to": token_address,
"data": token_identity_selector + token_identity_data,
}
)

name = decode(["string"], token_identity_result)[0]
self.assertEqual(name, expected_name)

token_identity_selector = self.function_selector("decimals()")
token_identity_data = encode([], [])
token_identity_result = self.web3.eth.call(
{
"to": token_address,
"data": token_identity_selector + token_identity_data,
}
)
self.assertEqual(
int.from_bytes(token_identity_result, "big"), expected_decimals
)

token_identity_selector = self.function_selector("symbol()")
token_identity_data = encode([], [])
token_identity_result = self.web3.eth.call(
{
"to": token_address,
"data": token_identity_selector + token_identity_data,
}
)

symbol = decode(["string"], token_identity_result)[0]
self.assertEqual(symbol, expected_symbol)

def test_02_mint_wbtc(self):
"""Test minting WBTC (Rust) to test account"""
self.mint_token(self.wbtc_address)

def test_03_mint_pi2(self):
"""Test minting PI2 (Simple) to test account"""
self.mint_token(self.pi2_address)

def test_04_mint_usdc(self):
"""Test minting USDC (Solidity) to test account"""
self.mint_token(self.usdc_address)

def test_05_mint_weth(self):
"""Test minting WETH (EVM) to test account"""
# Mint
mint_selector = self.function_selector("deposit()")
mint_data = encode([], [])
mint_tx = self.web3.eth.send_transaction(
{
"from": self.test_account_address,
"to": self.weth_address,
"data": mint_selector + mint_data,
"value": 10000000000000000,
}
)
mint_tx_receipt = self.web3.eth.wait_for_transaction_receipt(mint_tx)
self.assertEqual(mint_tx_receipt["status"], 1)

# Verify balance
get_token_balance_selector = self.function_selector("balanceOf(address)")
get_token_balance_data = encode(["address"], [self.test_account_address])
get_token_balance_result = self.web3.eth.call(
{
"to": self.weth_address,
"data": get_token_balance_selector + get_token_balance_data,
}
)
token_a_balance = int.from_bytes(get_token_balance_result, "big")

self.assertEqual(token_a_balance, 10000000000000000)

get_eth_balance_result = self.web3.eth.get_balance(self.weth_address)
self.assertEqual(get_eth_balance_result, 10000000000000000)

def test_06_approve_wbtc(self):
"""Test approving spending of WBTC (Rust)"""
self.approve_token(self.wbtc_address)

def test_07_approve_pi2(self):
"""Test approving spending of PI2 (Simple)"""
self.approve_token(self.pi2_address)

def test_08_approve_usdc(self):
"""Test approving spending of USDC (Solidity)"""
self.approve_token(self.usdc_address)

def test_09_approve_weth(self):
"""Test approving spending of WETH (EVM)"""
self.approve_token(self.weth_address)

def test_10_wbtc_identity(self):
"""Test WBTC (Rust) identity"""
self.check_token_identity(self.wbtc_address, "Wrapped Bitcoin", 18, "WBTC")

def test_11_pi2_identity(self):
"""Test PI2 (Simple) identity"""
self.check_token_identity(self.pi2_address, "Pi Squared", 18, "PI2")

def test_12_usdc_identity(self):
"""Test USDC (Solidity) identity"""
self.check_token_identity(self.usdc_address, "USD Coin", 18, "USDC")

def test_13_weth_identity(self):
"""Test WETH (EVM) identity"""
self.check_token_identity(self.weth_address, "Wrapped Ethereum", 18, "WETH")

if __name__ == "__main__":
pass

0 comments on commit d3f7068

Please sign in to comment.