-
Notifications
You must be signed in to change notification settings - Fork 3
/
simple_struct.cairo
80 lines (70 loc) · 2.58 KB
/
simple_struct.cairo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use box::BoxTrait;
use starknet::{
contract_address_const, get_tx_info, get_caller_address, testing::set_caller_address
};
use pedersen::PedersenTrait;
use hash::{HashStateTrait, HashStateExTrait};
const STARKNET_DOMAIN_TYPE_HASH: felt252 =
selector!("StarkNetDomain(name:felt,version:felt,chainId:felt)");
const SIMPLE_STRUCT_TYPE_HASH: felt252 =
selector!("SimpleStruct(some_felt252:felt,some_u128:u128)");
#[derive(Drop, Copy, Hash)]
struct SimpleStruct {
some_felt252: felt252,
some_u128: u128,
}
#[derive(Drop, Copy, Hash)]
struct StarknetDomain {
name: felt252,
version: felt252,
chain_id: felt252,
}
trait IStructHash<T> {
fn hash_struct(self: @T) -> felt252;
}
trait IOffchainMessageHash<T> {
fn get_message_hash(self: @T) -> felt252;
}
impl OffchainMessageHashSimpleStruct of IOffchainMessageHash<SimpleStruct> {
fn get_message_hash(self: @SimpleStruct) -> felt252 {
let domain = StarknetDomain {
name: 'dappName', version: 1, chain_id: get_tx_info().unbox().chain_id
};
let mut state = PedersenTrait::new(0);
state = state.update_with('StarkNet Message');
state = state.update_with(domain.hash_struct());
// This can be a field within the struct, it doesn't have to be get_caller_address().
state = state.update_with(get_caller_address());
state = state.update_with(self.hash_struct());
// Hashing with the amount of elements being hashed
state = state.update_with(4);
state.finalize()
}
}
impl StructHashStarknetDomain of IStructHash<StarknetDomain> {
fn hash_struct(self: @StarknetDomain) -> felt252 {
let mut state = PedersenTrait::new(0);
state = state.update_with(STARKNET_DOMAIN_TYPE_HASH);
state = state.update_with(*self);
state = state.update_with(4);
state.finalize()
}
}
impl StructHashSimpleStruct of IStructHash<SimpleStruct> {
fn hash_struct(self: @SimpleStruct) -> felt252 {
let mut state = PedersenTrait::new(0);
state = state.update_with(SIMPLE_STRUCT_TYPE_HASH);
state = state.update_with(*self);
state = state.update_with(3);
state.finalize()
}
}
#[test]
#[available_gas(2000000)]
fn test_valid_hash() {
// This value was computed using StarknetJS
let message_hash = 0x1e739b39f83b38f182edaed69f730f18eff802d3ef44be91c3733cdcab6de2f;
let simple_struct = SimpleStruct { some_felt252: 712, some_u128: 42 };
set_caller_address(contract_address_const::<420>());
assert(simple_struct.get_message_hash() == message_hash, 'Hash should be valid');
}