Skip to content
Merged
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
132 changes: 123 additions & 9 deletions tests/integration/test_integration_ip_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,14 @@ def test_executeWithSig(self, story_client):
token_id=token_id
)

ipId = response['ipId']
ip_id = response['ipId']
deadline = getBlockTimestamp(web3) + 100
state = story_client.IPAccount.getIpAccountNonce(ipId)
state = story_client.IPAccount.getIpAccountNonce(ip_id)

core_data = story_client.IPAccount.access_controller_client.contract.encode_abi(
abi_element_identifier="setTransientPermission",
args=[
ipId,
ip_id,
account.address,
"0x6E81a25C99C6e8430aeC7353325EB138aFE5DC16",
Web3.keccak(text="function setAll(address,string,bytes32,bytes32)")[:4],
Expand Down Expand Up @@ -141,7 +141,7 @@ def test_executeWithSig(self, story_client):
"name": "Story Protocol IP Account",
"version": "1",
"chainId": 1315,
"verifyingContract": ipId,
"verifyingContract": ip_id,
}

message_types = {
Expand All @@ -168,7 +168,7 @@ def test_executeWithSig(self, story_client):
response = story_client.IPAccount.executeWithSig(
to=story_client.IPAccount.access_controller_client.contract.address,
value=0,
ip_id=ipId,
ip_id=ip_id,
data=core_data,
signer=account.address,
deadline=deadline,
Expand Down Expand Up @@ -229,15 +229,13 @@ def test_execute_with_sig_multiple_permissions(self, story_client):
]
)

# Calculate the expected state
expected_state = Web3.keccak(
encode(
["bytes32", "bytes"],
[state, Web3.to_bytes(hexstr=execute_data)]
)
)

# Prepare signature data
domain_data = {
"name": "Story Protocol IP Account",
"version": "1",
Expand Down Expand Up @@ -343,6 +341,122 @@ def test_set_ip_metadata(self, story_client):
assert isinstance(response['txHash'], str), "'txHash' is not a string."
assert len(response['txHash']) > 0, "'txHash' is empty."

def test_execute_with_sig_wrong_signer(self, story_client):
"""Test executeWithSig with a valid signature but wrong signer address."""
token_id = get_token_id(MockERC721, story_client.web3, story_client.account)
register_response = story_client.IPAsset.register(
nft_contract=MockERC721,
token_id=token_id
)
ip_id = register_response['ipId']

deadline = getBlockTimestamp(web3) + 100
state = story_client.IPAccount.getIpAccountNonce(ip_id)
data = "0x"

execute_data = story_client.IPAccount.ip_account_client.contract.encode_abi(
abi_element_identifier="execute",
args=[
story_client.IPAccount.access_controller_client.contract.address,
0,
data
]
)

expected_state = Web3.keccak(
encode(
["bytes32", "bytes"],
[state, Web3.to_bytes(hexstr=execute_data)]
)
)

domain_data = {
"name": "Story Protocol IP Account",
"version": "1",
"chainId": 1315,
"verifyingContract": ip_id,
}

message_types = {
"Execute": [
{"name": "to", "type": "address"},
{"name": "value", "type": "uint256"},
{"name": "data", "type": "bytes"},
{"name": "nonce", "type": "bytes32"},
{"name": "deadline", "type": "uint256"},
],
}

message_data = {
"to": story_client.IPAccount.access_controller_client.contract.address,
"value": 0,
"data": data,
"nonce": expected_state,
"deadline": deadline,
}

signable_message = encode_typed_data(domain_data, message_types, message_data)
signed_message = Account.sign_message(signable_message, private_key)
wrong_signer = "0x1234567890123456789012345678901234567890"

with pytest.raises(Exception) as exc_info:
story_client.IPAccount.executeWithSig(
ip_id=ip_id,
to=story_client.IPAccount.access_controller_client.contract.address,
value=0,
data=data,
signer=wrong_signer, # Wrong signer address
deadline=deadline,
signature=signed_message.signature
)

print(f"Exception type: {type(exc_info.value)}")
print(f"Exception value: {exc_info.value}")
print(f"Exception args: {exc_info.value.args if hasattr(exc_info.value, 'args') else 'No args'}")

error_hex = '0x3fd60002'
assert error_hex in str(exc_info.value), f"Expected error code {error_hex} for wrong signer"

@pytest.mark.skip(reason="contract allows empty calls")
def test_transfer_erc20_empty_tokens(self, story_client):
"""Test transferERC20 with empty tokens list."""
token_id = get_token_id(MockERC721, story_client.web3, story_client.account)
register_response = story_client.IPAsset.register(
nft_contract=MockERC721,
token_id=token_id
)
ip_id = register_response['ipId']

# Try to transfer with empty tokens list
with pytest.raises(Exception) as exc_info:
story_client.IPAccount.transferERC20(
ip_id=ip_id,
tokens=[] # Empty tokens list
)

def test_transfer_erc20_invalid_token_params(self, story_client):
"""Test transferERC20 with invalid token parameters."""
token_id = get_token_id(MockERC721, story_client.web3, story_client.account)
register_response = story_client.IPAsset.register(
nft_contract=MockERC721,
token_id=token_id
)
ip_id = register_response['ipId']

with pytest.raises(ValueError) as exc_info:
story_client.IPAccount.transferERC20(
ip_id=ip_id,
tokens=[
{
# Missing 'address'
"target": story_client.account.address,
"amount": 1000000
}
]
)
assert "must include" in str(exc_info.value), "Error should mention missing parameter"


class TestTransferERC20:
"""Tests for transferring ERC20 tokens"""

Expand All @@ -355,7 +469,7 @@ def test_transfer_erc20(self, story_client):
)
ip_id = response['ipId']

# 1. Query token balance of ipId and wallet before
# 1. Query token balance of ip_id and wallet before
initial_erc20_balance_of_ip_id = story_client.Royalty.mock_erc20_client.balanceOf(
account=ip_id
)
Expand Down Expand Up @@ -413,7 +527,7 @@ def test_transfer_erc20(self, story_client):
]
)

# 5. Query token balance of ipId and wallet address after transfer
# 5. Query token balance of ip_id and wallet address after transfer
final_erc20_balance_of_ip_id = story_client.Royalty.mock_erc20_client.balanceOf(
account=ip_id
)
Expand Down