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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ Sign EIP-712 messages, such as settlements, using the `eip712` library.

```python
from ape import accounts, convert, chain
from tplus.evm.eip712 import Order
from tplus.utils.domain import Order
from tplus.evm.contracts import vault
from tplus.utils.user import UserManager

Expand Down
27 changes: 20 additions & 7 deletions tests/evm/test_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

from tplus.evm.constants import REGISTRY_ADDRESS
from tplus.evm.contracts import DepositVault, Registry, TPlusContract, _decode_erc20_error
from tplus.evm.eip712 import Domain
from tplus.evm.exceptions import ContractNotExists
from tplus.model.asset_identifier import ChainAddress
from tplus.utils.domain import get_dstack_domain


class TestTplusContract:
Expand Down Expand Up @@ -39,7 +39,8 @@ def test_address_from_lookup(self):
class TestDepositVault:
def test_deploy(self, accounts):
owner = accounts[0]
instance = DepositVault.deploy(sender=owner)
credential_manager = accounts[2]
instance = DepositVault.deploy(owner, credential_manager, sender=owner)
# It should know its address.
assert instance.address
assert instance.owner() == owner.address
Expand All @@ -48,31 +49,43 @@ def test_deploy_different_owner(self, accounts):
owner = accounts[0]
sender = accounts[1]
deployer_nonce_before = sender.nonce
instance = DepositVault.deploy(owner, sender=sender)
credential_manager = accounts[2]
instance = DepositVault.deploy(owner, credential_manager, sender=sender)
deployer_nonce_after = sender.nonce
# It should know its address.
assert instance.address
assert instance.owner() == owner.address
assert deployer_nonce_after > deployer_nonce_before

def test_from_chain_address(self):
address = ChainAddress(root="62622E77D1349Face943C6e7D5c01C61465FE1dc@000000000000aa36a7")
address = ChainAddress.from_str(
"62622E77D1349Face943C6e7D5c01C61465FE1dc@000000000000aa36a7"
)
vault = DepositVault.from_chain_address(address)
assert vault.address == address.evm_address

def test_domain_separator(self, accounts, chain):
owner = accounts[0]
credential_manager = accounts[2]

# Sets domain separator automatically.
instance = DepositVault.deploy(sender=owner)

expected = Domain(chain.chain_id, instance.address).separator
instance = DepositVault.deploy(owner, credential_manager, sender=owner)
expected = get_dstack_domain(instance.chain_address)
instance.set_domain_separator(expected, sender=owner)

# Reads using `eth_getStorageAt()` RPC.
actual = instance.domain_separator

assert actual == expected

def test_chain_address(self, accounts):
owner = accounts[0]
instance = DepositVault.deploy(owner, owner, sender=owner)
actual = instance.chain_address
assert actual.evm_address == instance.address
assert actual.chain_id.routing_id == 0
assert actual.chain_id.vm_id == accounts.chain_manager.chain_id


@pytest.mark.parametrize("error", ("TransferFromFailed()", "TransferFailed()"))
def test_decode_erc20_error(error):
Expand Down
32 changes: 0 additions & 32 deletions tests/evm/test_eip712.py

This file was deleted.

23 changes: 1 addition & 22 deletions tests/model/test_asset_identifier.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,6 @@
import pytest

from tplus.model.asset_identifier import AssetIdentifier, ChainAddress


class TestChainAddress:
@pytest.fixture(scope="class")
def chain_address(self):
return ChainAddress(root="62622E77D1349Face943C6e7D5c01C61465FE1dc@000000000000aa36a7")

def test_address(self, chain_address):
assert (
chain_address.address
== "62622e77d1349face943c6e7d5c01c61465fe1dc000000000000000000000000"
)

def test_evm_address(self, chain_address):
"""
Evm address should be 20 bytes and checksummed.
"""
assert chain_address.evm_address == "0x62622E77D1349Face943C6e7D5c01C61465FE1dc"

def test_chain_id(self, chain_address):
assert chain_address.chain_id.vm_id == 11155111
from tplus.model.asset_identifier import AssetIdentifier


class TestAssetIdentifier:
Expand Down
30 changes: 30 additions & 0 deletions tests/model/test_chain_address.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import pytest

from tplus.model.asset_identifier import ChainAddress


class TestChainAddress:
@pytest.fixture(scope="class")
def chain_address(self):
return ChainAddress.from_str("62622E77D1349Face943C6e7D5c01C61465FE1dc@000000000000aa36a7")

def test_from_evm_address(self):
evm_address = "62622E77D1349Face943C6e7D5c01C61465FE1dc"
chain_address = ChainAddress.from_evm_address(evm_address, 123)
assert chain_address.evm_address == f"0x{evm_address}"
assert chain_address.chain_id.vm_id == 123

def test_address(self, chain_address):
assert (
chain_address.address
== "62622e77d1349face943c6e7d5c01c61465fe1dc000000000000000000000000"
)

def test_evm_address(self, chain_address):
"""
Evm address should be 20 bytes and checksummed.
"""
assert chain_address.evm_address == "0x62622E77D1349Face943C6e7D5c01C61465FE1dc"

def test_chain_id(self, chain_address):
assert chain_address.chain_id.vm_id == 11155111
26 changes: 13 additions & 13 deletions tests/utils/test_decimals.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,34 @@

from tplus.constants import CLEARING_ENGINE_DECIMALS
from tplus.utils.decimals import (
normalize_decimals,
normalize_from_inventory,
normalize_to_inventory,
convert_decimals,
to_chain_decimals,
to_inventory_decimals,
)


def test_normalize_decimals_equal():
assert normalize_decimals(12345, 6, 6, "down") == 12345
assert convert_decimals(12345, 6, 6, "down") == 12345


def test_normalize_decimals_scale_up():
# from 6 decimals to 18 decimals
amount = 12345
result = normalize_decimals(amount, 6, 18, "down")
result = convert_decimals(amount, 6, 18, "down")
assert result == amount * 10**12


def test_normalize_decimals_scale_down_round_down():
# from 18 decimals to 6 decimals, round down
amount = 123456789000000000000 # 123.456789 tokens at 18 decimals
result = normalize_decimals(amount, 18, 6, "down")
result = convert_decimals(amount, 18, 6, "down")
assert result == amount // 10**12


def test_normalize_decimals_scale_down_round_up():
# from 18 decimals to 6 decimals, round up
amount = 123456789000000000001 # just slightly above
result = normalize_decimals(amount, 18, 6, "up")
result = convert_decimals(amount, 18, 6, "up")
expected = (amount + (10**12 - 1)) // 10**12
assert result == expected
# Verify it's strictly greater than floor division
Expand All @@ -39,16 +39,16 @@ def test_normalize_decimals_scale_down_round_up():
def test_normalize_to_inventory_matches_manual():
amount = 1000
decimals = 6
result = normalize_to_inventory(amount, decimals, "down")
expected = normalize_decimals(amount, decimals, CLEARING_ENGINE_DECIMALS, "down")
result = to_inventory_decimals(amount, decimals, "down")
expected = convert_decimals(amount, decimals, CLEARING_ENGINE_DECIMALS, "down")
assert result == expected


def test_normalize_from_inventory_matches_manual():
amount = 10**18 # 1.0 in 18-decimal units
decimals = 6
result = normalize_from_inventory(amount, decimals, "down")
expected = normalize_decimals(amount, CLEARING_ENGINE_DECIMALS, decimals, "down")
result = to_chain_decimals(amount, decimals, "down")
expected = convert_decimals(amount, CLEARING_ENGINE_DECIMALS, decimals, "down")
assert result == expected


Expand All @@ -60,8 +60,8 @@ def test_roundtrip_invertible(rounding):
"""
amount = 987654321
decimals = 6
to_inventory = normalize_to_inventory(amount, decimals, rounding)
back = normalize_from_inventory(to_inventory, decimals, rounding)
to_inventory = to_inventory_decimals(amount, decimals, rounding)
back = to_chain_decimals(to_inventory, decimals, rounding)

if rounding == "down":
assert back == amount
Expand Down
15 changes: 15 additions & 0 deletions tests/utils/test_domain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from eth_pydantic_types.hex.bytes import HexBytes32

from tplus.model.chain_address import ChainAddress
from tplus.utils.domain import get_dstack_domain


def test_get_dstack_domain():
address = "8800a71ad5201f7f3cc519a20c6cdf8c29297ea3000000000000000000000000"
vault = ChainAddress.from_str(f"{address}@000000000000007a69")
actual = get_dstack_domain(vault)

# Same as what backend produces.
expected = HexBytes32("2fb413e7c1cc1665bf930f80ab45477865105e67f74ffdb1a1ec3f6c05bff9a2")

assert actual == expected, f"Expected {expected.hex()}, got {actual.hex()}"
9 changes: 5 additions & 4 deletions tplus/client/clearingengine/settlement.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from tplus.client.clearingengine.base import BaseClearingEngineClient
from tplus.model.asset_identifier import ChainAddress
from tplus.model.settlement import BatchSettlementRequest, TxSettlementRequest
from tplus.model.types import ChainID
from tplus.model.types import ChainID, UserPublicKey


class SettlementClient(BaseClearingEngineClient):
Expand Down Expand Up @@ -118,15 +118,16 @@ async def update_approved_settlers(self, chain_id: ChainID, vault_address: str):
chain_id (int): The chain ID to check.
vault_address (str): The vault address to check.
"""
request = ChainAddress(f"{vault_address}@{chain_id}")
request = ChainAddress.from_str(f"{vault_address}@{chain_id}")
json_data = request.model_dump(mode="json")
await self._post("settlers/update", json_data=json_data)

async def get_approved_settlers(self, chain_id: ChainID) -> list[str]:
async def get_approved_settlers(self, chain_id: ChainID) -> list[UserPublicKey]:
"""
Request that the CE check the deposit vault for new approved settlers.

Args:
chain_id (int): The chain ID to check.
"""
return await self._get(f"settlers/{chain_id}") # type: ignore
result = await self._get(f"settlers/{chain_id}") # type: ignore
return [UserPublicKey.__validate_user__(s) for s in result]
2 changes: 1 addition & 1 deletion tplus/evm/constants.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
REGISTRY_ADDRESS = "0xBBd0020ae0DAB578515d0c72EdFf37Bf30D31BE5"
REGISTRY_ADDRESS = "0x9700c54DFB6C8a77bA151556a41dC035B60e4B91"
LATEST_ARB_DEPOSIT_VAULT = "0x7a9eAA74eF31ed3eca5447252b443651Ad250916"
Loading