Skip to content

Commit 0e0161f

Browse files
authored
Merge pull request #30 from argentlabs/feature/clean_after_multicall
Clean after multicall
2 parents 1840190 + 36ef6b9 commit 0e0161f

File tree

5 files changed

+54
-53
lines changed

5 files changed

+54
-53
lines changed

contracts/ArgentAccount.cairo

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const ESCAPE_SECURITY_PERIOD = 7*24*60*60 # set to e.g. 7 days in prod
4040
const ESCAPE_TYPE_GUARDIAN = 0
4141
const ESCAPE_TYPE_SIGNER = 1
4242
43-
const ERC156_ACCOUNT_INTERFACE = 0x50b70dcb
43+
const ERC156_ACCOUNT_INTERFACE = 0xf10dbd44
4444
4545
const TRUE = 1
4646
const FALSE = 0
@@ -51,18 +51,20 @@ const PREFIX_TRANSACTION = 'StarkNet Transaction'
5151
# STRUCTS
5252
####################
5353
54-
struct MCall:
54+
struct Call:
5555
member to: felt
5656
member selector: felt
57-
member data_offset: felt
58-
member data_len: felt
57+
member calldata_len: felt
58+
member calldata: felt*
5959
end
6060
61-
struct Call:
61+
# Tmp struct introduced while we wait for Cairo
62+
# to support passing `[Call]` to __execute__
63+
struct CallArray:
6264
member to: felt
6365
member selector: felt
64-
member calldata_len: felt
65-
member calldata: felt*
66+
member data_offset: felt
67+
member data_len: felt
6668
end
6769
6870
struct Escape:
@@ -165,8 +167,8 @@ func __execute__{
165167
ecdsa_ptr: SignatureBuiltin*,
166168
range_check_ptr
167169
} (
168-
mcalls_len: felt,
169-
mcalls: MCall*,
170+
call_array_len: felt,
171+
call_array: CallArray*,
170172
calldata_len: felt,
171173
calldata: felt*,
172174
nonce: felt
@@ -179,8 +181,8 @@ func __execute__{
179181
############### TMP #############################
180182
# parse inputs to an array of 'Call' struct
181183
let (calls : Call*) = alloc()
182-
from_mcall_to_call(mcalls_len, mcalls, calldata, calls)
183-
let calls_len = mcalls_len
184+
from_call_array_to_call(call_array_len, call_array, calldata, calls)
185+
let calls_len = call_array_len
184186
#################################################
185187
186188
# validate and bump nonce
@@ -190,20 +192,20 @@ func __execute__{
190192
let (tx_info) = get_tx_info()
191193
192194
# compute message hash
193-
let (message_hash) = get_execute_hash(tx_info.account_contract_address, calls_len, calls, nonce, tx_info.max_fee, tx_info.version)
195+
let (hash) = hash_multicall(tx_info.account_contract_address, calls_len, calls, nonce, tx_info.max_fee, tx_info.version)
194196
195197
if calls_len == 1:
196198
if calls[0].to == tx_info.account_contract_address:
197199
tempvar signer_condition = (calls[0].selector - ESCAPE_GUARDIAN_SELECTOR) * (calls[0].selector - TRIGGER_ESCAPE_GUARDIAN_SELECTOR)
198200
tempvar guardian_condition = (calls[0].selector - ESCAPE_SIGNER_SELECTOR) * (calls[0].selector - TRIGGER_ESCAPE_SIGNER_SELECTOR)
199201
if signer_condition == 0:
200202
# validate signer signature
201-
validate_signer_signature(message_hash, tx_info.signature, tx_info.signature_len)
203+
validate_signer_signature(hash, tx_info.signature, tx_info.signature_len)
202204
jmp do_execute
203205
end
204206
if guardian_condition == 0:
205207
# validate guardian signature
206-
validate_guardian_signature(message_hash, tx_info.signature, tx_info.signature_len)
208+
validate_guardian_signature(hash, tx_info.signature, tx_info.signature_len)
207209
jmp do_execute
208210
end
209211
end
@@ -212,8 +214,8 @@ func __execute__{
212214
assert_no_self_call(tx_info.account_contract_address, calls_len, calls)
213215
end
214216
# validate signer and guardian signatures
215-
validate_signer_signature(message_hash, tx_info.signature, tx_info.signature_len)
216-
validate_guardian_signature(message_hash, tx_info.signature + 2, tx_info.signature_len - 2)
217+
validate_signer_signature(hash, tx_info.signature, tx_info.signature_len)
218+
validate_guardian_signature(hash, tx_info.signature + 2, tx_info.signature_len - 2)
217219
218220
# execute calls
219221
do_execute:
@@ -719,7 +721,7 @@ end
719721
# @param max_fee The max fee the user is willing to pay for the multicall
720722
# @param version The version of transaction in the Cairo OS. Always set to 0.
721723
# @return res The hash of the multicall
722-
func get_execute_hash{
724+
func hash_multicall{
723725
syscall_ptr: felt*,
724726
pedersen_ptr: HashBuiltin*
725727
} (
@@ -826,31 +828,28 @@ func hash_calldata{
826828
end
827829
end
828830
829-
func from_mcall_to_call{
830-
syscall_ptr: felt*,
831-
pedersen_ptr: HashBuiltin*,
832-
range_check_ptr
831+
func from_call_array_to_call{
832+
syscall_ptr: felt*
833833
} (
834-
mcalls_len: felt,
835-
mcalls: MCall*,
834+
call_array_len: felt,
835+
call_array: CallArray*,
836836
calldata: felt*,
837837
calls: Call*
838838
):
839-
alloc_locals
840-
841-
# if no more mcalls
842-
if mcalls_len == 0:
839+
# if no more calls
840+
if call_array_len == 0:
843841
return ()
844842
end
845843
846-
# parse the first mcall
844+
# parse the current call
847845
assert [calls] = Call(
848-
to=[mcalls].to,
849-
selector=[mcalls].selector,
850-
calldata_len=[mcalls].data_len,
851-
calldata=calldata + [mcalls].data_offset)
846+
to=[call_array].to,
847+
selector=[call_array].selector,
848+
calldata_len=[call_array].data_len,
849+
calldata=calldata + [call_array].data_offset
850+
)
852851
853-
# parse the other mcalls recursively
854-
from_mcall_to_call(mcalls_len - 1, mcalls + MCall.SIZE, calldata, calls + Call.SIZE)
852+
# parse the remaining calls recursively
853+
from_call_array_to_call(call_array_len - 1, call_array + CallArray.SIZE, calldata, calls + Call.SIZE)
855854
return ()
856855
end

test/argent_account.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
VERSION = str_to_felt('0.2.0')
2626

27+
IACCOUNT_ID = 0xf10dbd44
28+
2729
ESCAPE_TYPE_GUARDIAN = 0
2830
ESCAPE_TYPE_SIGNER = 1
2931

@@ -62,7 +64,8 @@ async def test_initializer(account_factory):
6264
assert (await account.get_signer().call()).result.signer == (signer.public_key)
6365
assert (await account.get_guardian().call()).result.guardian == (guardian.public_key)
6466
assert (await account.get_version().call()).result.version == VERSION
65-
# should throw when calling initialize
67+
assert (await account.supportsInterface(IACCOUNT_ID).call()).result.success == 1
68+
# should throw when calling initialize twice
6669
await assert_revert(
6770
account.initialize(signer.public_key, guardian.public_key).invoke()
6871
)

test/utils/Signer.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from starkware.crypto.signature.signature import pedersen_hash, private_to_stark_key, sign
2-
from starkware.starknet.public.abi import get_selector_from_name
1+
from starkware.crypto.signature.signature import private_to_stark_key, sign
32

43

54
class Signer():

test/utils/TransactionSender.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,28 @@ async def send_transaction(self, calls, signers, nonce=None, max_fee=0):
1717
execution_info = await self.account.get_nonce().call()
1818
nonce = execution_info.result.nonce
1919

20-
call_inputs = []
21-
calls_with_selector = []
22-
calldata = []
23-
for i in range(len(calls)):
24-
if len(calls[i]) != 3:
25-
raise Exception("Invalid call parameters")
26-
call = calls[i]
27-
call_input = (call[0], get_selector_from_name(call[1]), len(calldata), len(call[2]))
28-
call_inputs.append(call_input)
29-
calldata.extend(call[2])
30-
calls_with_selector.append((call[0], get_selector_from_name(call[1]), call[2]))
20+
calls_with_selector = [(call[0], get_selector_from_name(call[1]), call[2]) for call in calls]
21+
call_array, calldata = from_call_to_call_array(calls)
3122

3223
message_hash = hash_multicall(self.account.contract_address, calls_with_selector, nonce, max_fee)
3324
signatures = []
3425
for signer in signers:
3526
if signer == 0:
36-
signatures += list([0, 0])
27+
signatures += [0, 0]
3728
else:
3829
signatures += list(signer.sign(message_hash))
3930

40-
return await self.account.__execute__(call_inputs, calldata, nonce).invoke(signature=signatures)
31+
return await self.account.__execute__(call_array, calldata, nonce).invoke(signature=signatures)
32+
33+
def from_call_to_call_array(calls):
34+
call_array = []
35+
calldata = []
36+
for call in calls:
37+
assert len(call) == 3, "Invalid call parameters"
38+
entry = (call[0], get_selector_from_name(call[1]), len(calldata), len(call[2]))
39+
call_array.append(entry)
40+
calldata.extend(call[2])
41+
return call_array, calldata
4142

4243
def hash_multicall(account, calls, nonce, max_fee):
4344
hash_array = []

test/utils/utilities.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import os
22
from starkware.starknet.testing.contract import StarknetContract
33
from starkware.starknet.compiler.compile import compile_starknet_files
4-
from starkware.starknet.testing.state import StarknetState
54
from starkware.starkware_utils.error_handling import StarkException
65
from starkware.starknet.definitions.error_codes import StarknetErrorCode
76
from starkware.starknet.business_logic.transaction_execution_objects import Event
@@ -12,7 +11,7 @@ def str_to_felt(text):
1211
return int.from_bytes(b_text, "big")
1312

1413
def uint(a):
15-
return(a, 0)
14+
return a, 0
1615

1716
async def assert_revert(expression, expected_message=None, expected_code=None):
1817
if expected_code is None:
@@ -49,7 +48,7 @@ async def deploy_proxy(starknet, proxy_path, implementation_path, params=None):
4948
params = params or []
5049
proxy_definition = compile_starknet_files([proxy_path], debug_info=True)
5150
implementation_definition = compile_starknet_files([implementation_path], debug_info=True)
52-
deployed_proxy = await starknet.deploy(contract_def=proxy_definition,constructor_calldata=params)
51+
deployed_proxy = await starknet.deploy(contract_def=proxy_definition, constructor_calldata=params)
5352
wrapped_proxy = StarknetContract(
5453
state=starknet.state,
5554
abi=implementation_definition.abi,

0 commit comments

Comments
 (0)