module EVM.Concrete where
import EVM.RLP
import EVM.Types
import Data.Bits (Bits(..), shiftR)
import Data.ByteString (ByteString, (!?))
import Data.ByteString qualified as BS
import Data.Maybe (fromMaybe)
import Data.Word (Word8)
import Witch (unsafeInto)
wordAt :: Int -> ByteString -> W256
wordAt :: Int -> ByteString -> W256
wordAt Int
i ByteString
bs =
ByteString -> W256
word (Int -> ByteString -> ByteString
padRight Int
32 (Int -> ByteString -> ByteString
BS.drop Int
i ByteString
bs))
readByteOrZero :: Int -> ByteString -> Word8
readByteOrZero :: Int -> ByteString -> Word8
readByteOrZero Int
i ByteString
bs = forall a. a -> Maybe a -> a
fromMaybe Word8
0 (ByteString
bs ByteString -> Int -> Maybe Word8
!? Int
i)
byteStringSliceWithDefaultZeroes :: Int -> Int -> ByteString -> ByteString
byteStringSliceWithDefaultZeroes :: Int -> Int -> ByteString -> ByteString
byteStringSliceWithDefaultZeroes Int
offset Int
size ByteString
bs =
if Int
size forall a. Eq a => a -> a -> Bool
== Int
0
then ByteString
""
else
let bs' :: ByteString
bs' = Int -> ByteString -> ByteString
BS.take Int
size (Int -> ByteString -> ByteString
BS.drop Int
offset ByteString
bs)
in ByteString
bs' forall a. Semigroup a => a -> a -> a
<> Int -> Word8 -> ByteString
BS.replicate (Int
size forall a. Num a => a -> a -> a
- ByteString -> Int
BS.length ByteString
bs') Word8
0
sliceMemory :: W256 -> W256 -> ByteString -> ByteString
sliceMemory :: W256 -> W256 -> ByteString -> ByteString
sliceMemory W256
o W256
s =
Int -> Int -> ByteString -> ByteString
byteStringSliceWithDefaultZeroes (forall target source.
(HasCallStack, TryFrom source target, Show source, Typeable source,
Typeable target) =>
source -> target
unsafeInto W256
o) (forall target source.
(HasCallStack, TryFrom source target, Show source, Typeable source,
Typeable target) =>
source -> target
unsafeInto W256
s)
writeMemory :: ByteString -> W256 -> W256 -> W256 -> ByteString -> ByteString
writeMemory :: ByteString -> W256 -> W256 -> W256 -> ByteString -> ByteString
writeMemory ByteString
bs1 W256
n W256
src W256
dst ByteString
bs0 =
let
(ByteString
a, ByteString
b) = Int -> ByteString -> (ByteString, ByteString)
BS.splitAt (forall target source.
(HasCallStack, TryFrom source target, Show source, Typeable source,
Typeable target) =>
source -> target
unsafeInto W256
dst) ByteString
bs0
a' :: ByteString
a' = Int -> Word8 -> ByteString
BS.replicate (forall target source.
(HasCallStack, TryFrom source target, Show source, Typeable source,
Typeable target) =>
source -> target
unsafeInto W256
dst forall a. Num a => a -> a -> a
- ByteString -> Int
BS.length ByteString
a) Word8
0
c :: ByteString
c = if W256
src forall a. Ord a => a -> a -> Bool
> forall target source.
(HasCallStack, TryFrom source target, Show source, Typeable source,
Typeable target) =>
source -> target
unsafeInto (ByteString -> Int
BS.length ByteString
bs1)
then Int -> Word8 -> ByteString
BS.replicate (forall target source.
(HasCallStack, TryFrom source target, Show source, Typeable source,
Typeable target) =>
source -> target
unsafeInto W256
n) Word8
0
else W256 -> W256 -> ByteString -> ByteString
sliceMemory W256
src W256
n ByteString
bs1
b' :: ByteString
b' = Int -> ByteString -> ByteString
BS.drop (forall target source.
(HasCallStack, TryFrom source target, Show source, Typeable source,
Typeable target) =>
source -> target
unsafeInto W256
n) ByteString
b
in
ByteString
a forall a. Semigroup a => a -> a -> a
<> ByteString
a' forall a. Semigroup a => a -> a -> a
<> ByteString
c forall a. Semigroup a => a -> a -> a
<> ByteString
b'
(^) :: W256 -> W256 -> W256
W256
x0 ^ :: W256 -> W256 -> W256
^ W256
y0 | W256
y0 forall a. Ord a => a -> a -> Bool
< W256
0 = forall a. [Char] -> a
errorWithoutStackTrace [Char]
"Negative exponent"
| W256
y0 forall a. Eq a => a -> a -> Bool
== W256
0 = W256
1
| Bool
otherwise = forall {a} {t}. (Bits a, Num t, Num a) => t -> a -> t
f W256
x0 W256
y0
where
f :: t -> a -> t
f t
x a
y | Bool -> Bool
not (forall a. Bits a => a -> Int -> Bool
testBit a
y Int
0) = t -> a -> t
f (t
x forall a. Num a => a -> a -> a
* t
x) (a
y forall a. Bits a => a -> Int -> a
`shiftR` Int
1)
| a
y forall a. Eq a => a -> a -> Bool
== a
1 = t
x
| Bool
otherwise = forall {a} {t}. (Bits a, Num t, Num a) => t -> a -> t -> t
g (t
x forall a. Num a => a -> a -> a
* t
x) ((a
y forall a. Num a => a -> a -> a
- a
1) forall a. Bits a => a -> Int -> a
`shiftR` Int
1) t
x
g :: t -> a -> t -> t
g t
x a
y t
z | Bool -> Bool
not (forall a. Bits a => a -> Int -> Bool
testBit a
y Int
0) = t -> a -> t -> t
g (t
x forall a. Num a => a -> a -> a
* t
x) (a
y forall a. Bits a => a -> Int -> a
`shiftR` Int
1) t
z
| a
y forall a. Eq a => a -> a -> Bool
== a
1 = t
x forall a. Num a => a -> a -> a
* t
z
| Bool
otherwise = t -> a -> t -> t
g (t
x forall a. Num a => a -> a -> a
* t
x) ((a
y forall a. Num a => a -> a -> a
- a
1) forall a. Bits a => a -> Int -> a
`shiftR` Int
1) (t
x forall a. Num a => a -> a -> a
* t
z)
createAddress :: Addr -> W256 -> Addr
createAddress :: Addr -> W256 -> Addr
createAddress Addr
a W256
n = forall target source.
(HasCallStack, TryFrom source target, Show source, Typeable source,
Typeable target) =>
source -> target
unsafeInto forall a b. (a -> b) -> a -> b
$ ByteString -> W256
keccak' forall a b. (a -> b) -> a -> b
$ [RLP] -> ByteString
rlpList [Addr -> RLP
rlpAddrFull Addr
a, W256 -> RLP
rlpWord256 W256
n]
create2Address :: Addr -> W256 -> ByteString -> Addr
create2Address :: Addr -> W256 -> ByteString -> Addr
create2Address Addr
a W256
s ByteString
b = forall target source.
(HasCallStack, TryFrom source target, Show source, Typeable source,
Typeable target) =>
source -> target
unsafeInto forall a b. (a -> b) -> a -> b
$ ByteString -> W256
keccak' forall a b. (a -> b) -> a -> b
$ forall a. Monoid a => [a] -> a
mconcat
[Word8 -> ByteString
BS.singleton Word8
0xff, Addr -> ByteString
word160Bytes Addr
a, W256 -> ByteString
word256Bytes W256
s, W256 -> ByteString
word256Bytes forall a b. (a -> b) -> a -> b
$ ByteString -> W256
keccak' ByteString
b]