-
Notifications
You must be signed in to change notification settings - Fork 352
/
library.cairo
119 lines (104 loc) · 3.6 KB
/
library.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# SPDX-License-Identifier: MIT
# OpenZeppelin Contracts for Cairo v0.3.2 (security/safemath/library.cairo)
%lang starknet
from starkware.cairo.common.cairo_builtins import HashBuiltin
from starkware.cairo.common.bool import TRUE, FALSE
from starkware.cairo.common.uint256 import (
Uint256, uint256_check, uint256_add, uint256_sub, uint256_mul,
uint256_unsigned_div_rem, uint256_le, uint256_lt, uint256_eq
)
namespace SafeUint256:
# Adds two integers.
# Reverts if the sum overflows.
func add{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
} (a: Uint256, b: Uint256) -> (c: Uint256):
uint256_check(a)
uint256_check(b)
let (c: Uint256, is_overflow) = uint256_add(a, b)
with_attr error_message("SafeUint256: addition overflow"):
assert is_overflow = FALSE
end
return (c)
end
# Subtracts two integers.
# Reverts if minuend (`b`) is greater than subtrahend (`a`).
func sub_le{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
} (a: Uint256, b: Uint256) -> (c: Uint256):
alloc_locals
uint256_check(a)
uint256_check(b)
let (is_le) = uint256_le(b, a)
with_attr error_message("SafeUint256: subtraction overflow"):
assert is_le = TRUE
end
let (c: Uint256) = uint256_sub(a, b)
return (c)
end
# Subtracts two integers.
# Reverts if minuend (`b`) is greater than or equal to subtrahend (`a`).
func sub_lt{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
} (a: Uint256, b: Uint256) -> (c: Uint256):
alloc_locals
uint256_check(a)
uint256_check(b)
let (is_lt) = uint256_lt(b, a)
with_attr error_message("SafeUint256: subtraction overflow or the difference equals zero"):
assert is_lt = TRUE
end
let (c: Uint256) = uint256_sub(a, b)
return (c)
end
# Multiplies two integers.
# Reverts if product is greater than 2^256.
func mul{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
} (a: Uint256, b: Uint256) -> (c: Uint256):
alloc_locals
uint256_check(a)
uint256_check(b)
let (a_zero) = uint256_eq(a, Uint256(0, 0))
if a_zero == TRUE:
return (a)
end
let (b_zero) = uint256_eq(b, Uint256(0, 0))
if b_zero == TRUE:
return (b)
end
let (c: Uint256, overflow: Uint256) = uint256_mul(a, b)
with_attr error_message("SafeUint256: multiplication overflow"):
assert overflow = Uint256(0, 0)
end
return (c)
end
# Integer division of two numbers. Returns uint256 quotient and remainder.
# Reverts if divisor is zero as per OpenZeppelin's Solidity implementation.
# Cairo's `uint256_unsigned_div_rem` already checks:
# remainder < divisor
# quotient * divisor + remainder == dividend
func div_rem{
syscall_ptr: felt*,
pedersen_ptr: HashBuiltin*,
range_check_ptr
} (a: Uint256, b: Uint256) -> (c: Uint256, rem: Uint256):
alloc_locals
uint256_check(a)
uint256_check(b)
let (is_zero) = uint256_eq(b, Uint256(0, 0))
with_attr error_message("SafeUint256: divisor cannot be zero"):
assert is_zero = FALSE
end
let (c: Uint256, rem: Uint256) = uint256_unsigned_div_rem(a, b)
return (c, rem)
end
end