Transaction Hash:
Block:
16364839 at Jan-08-2023 09:44:47 PM +UTC
Transaction Fee:
0.014579601375262756 ETH
$29.94
Gas Used:
593,201 Gas / 24.577843556 Gwei
Emitted Events:
| 258 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000000224c7fc8bc1d12da3959c07e78646add7fd4da4, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 259 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000000811e06c09f9e39b04b9896dcb498deaf51983b8, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 260 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x00000000000000000000000014235a0de09871a93f47c0558a837250124a27ba, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 261 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000001b0d2d718c7ddc2955554cd8953d43f17190a0a0, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 262 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000002c393b90b7fb1926ca2aa57445f1c76b2b68fca9, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 263 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x00000000000000000000000034912efc0ef9d0b44acfd38c55af69d6a031e72d, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 264 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000003674840e64a5b2176052d9f65a9ac7e8dbf7bd5f, 00000000000000000000000000000000000000000000000001e2120dbda33200 )
|
| 265 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000378a654965facfc5b2d8156177cef54c43944ed4, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 266 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000003893f2ff234739b39dc88e8017e97828fe5287b2, 00000000000000000000000000000000000000000000000000c0d40596e59800 )
|
| 267 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x00000000000000000000000042d763414fec04f3d6c0cf902cb2ae4980328e57, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 268 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000004e29a366d1c9a92d449f450cbcbd4aafc42c80d2, 00000000000000000000000000000000000000000000000000c0d40596e59800 )
|
| 269 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x00000000000000000000000061e1c419d68e6b7484ff05cd611b531fe35c0643, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 270 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000653125a8c0352923fb45252d3fcab320fa2f19a3, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 271 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000007072fc60a6c6b913d78035935e733a24bac1dee4, 00000000000000000000000000000000000000000000000001213e0862586400 )
|
| 272 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x00000000000000000000000072b40caa258c237c6f5947e291650808b913e9fc, 00000000000000000000000000000000000000000000000000c0d40596e59800 )
|
| 273 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000007a6a9596af512a7e5b1ef331a70015cd3defa1f2, 00000000000000000000000000000000000000000000000000c0d40596e59800 )
|
| 274 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000007d6693ab8b51db8f4cd3be2900d0f2d9aa068eba, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 275 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x00000000000000000000000084490c42930b6648ef28851e6698a911904d8a04, 00000000000000000000000000000000000000000000000001e2120dbda33200 )
|
| 276 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000008fee92a2c1a6b7ea67ad9580d9585ee1a362acf4, 00000000000000000000000000000000000000000000000001213e0862586400 )
|
| 277 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x0000000000000000000000009194e2d1b507632eb5c76b64a00041968ee40de1, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 278 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x00000000000000000000000091c29d30090c77eccde977ea530d6385459871d9, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 279 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x00000000000000000000000091d5efd15df4c6542bc462d05c69a4984aba4228, 00000000000000000000000000000000000000000000000001213e0862586400 )
|
| 280 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000a0d9665e163f498082cd73048da17e7d69fd9224, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 281 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000a4ec64dcdd70b37a587f7583ee7feaab072bf724, 00000000000000000000000000000000000000000000000000c0d40596e59800 )
|
| 282 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000a949dcc3e472a4d62795c310c419395b70c6a792, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 283 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000b890f264b1a7591cdf9e21b3b640a741cf677ae9, 00000000000000000000000000000000000000000000000001e2120dbda33200 )
|
| 284 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000bf680ad4439588d92b33ff78bdff37a19eadc65e, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 285 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000cc86412afb2eefc3862d723ddef41fe9311a49e3, 00000000000000000000000000000000000000000000000001213e0862586400 )
|
| 286 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000cde0398a96741b19ccb4c8edfc96f630ec2ee10a, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 287 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000ce25fd73afcc36cb33916ba07732c9e33f2b0d0f, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 288 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000d88ed83743a1f04bd6988094dd049a6b3cc21726, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 289 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000d990d64b44a46bf0dc93ae884de96a787f99f312, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 290 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000d997e882f387578e33af9764351fccee8ac2b909, 0000000000000000000000000000000000000000000000000181a80b2dcb3000 )
|
| 291 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000dfe61ca71aa5931243de3fb38f481180220f3b0b, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 292 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000e75d7d7b6b8674630eadadd9f6ae1136f7fc6e9a, 00000000000000000000000000000000000000000000000000c0d40596e59800 )
|
| 293 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000e88ceb8eb0566551ade8c9b398b16ada25834a70, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 294 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000ecd495c47defe203bdd25d6bc7a412033cebe2f5, 0000000000000000000000000000000000000000000000000181a80b2dcb3000 )
|
| 295 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000efd192b6ecca66f3e00e3e1b498c6f91016bef6c, 00000000000000000000000000000000000000000000000001213e0862586400 )
|
| 296 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000f6bf64685f9a44bd96da7859785f0140c43b66a7, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 297 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000fae94c4b2c82f2aa2eb065da642642764a80eea1, 00000000000000000000000000000000000000000000000000c0d40596e59800 )
|
| 298 |
0x88777bccb752b20245400049021cb47b8fbcf640.0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e( 0x506e233c468e0d851eb903baaae437470eabd226863feb2dba8632412597fb7e, 0x000000000000000000000000c539a16028b4168490dc42080c02f28134e14bd1, 0x000000000000000000000000fd3c5b8be7783cd90169d2e4bc920833c14ab50f, 00000000000000000000000000000000000000000000000000606a02cb72cc00 )
|
| 299 |
0xc539a16028b4168490dc42080c02f28134e14bd1.0x3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d( 0x3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d, 0x00000000000000000000000088777bccb752b20245400049021cb47b8fbcf640, 0000000000000000000000000000000000000000000000000000000000000000 )
|
| 300 |
0xc539a16028b4168490dc42080c02f28134e14bd1.0x442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e( 0x442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e, 7df8a7eac676afe5dba4a8c60aba415e82d24beca9717186b84c01b856cf28f7, 0000000000000000000000000000000000000000000000000000000000000000 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x0224c7fC...dD7fD4dA4 | 0.001260692905306423 Eth | 0.028398850905306423 Eth | 0.027138158 | ||
| 0x0811e06C...AF51983b8 | 0.437054999512498858 Eth | 0.464193157512498858 Eth | 0.027138158 | ||
| 0x14235A0d...0124A27ba | 0.235535585525125316 Eth | 0.262673743525125316 Eth | 0.027138158 | ||
| 0x1B0d2d71...17190a0a0 | 13.129159599225423736 Eth | 13.156297757225423736 Eth | 0.027138158 | ||
| 0x2C393b90...B2B68Fca9 | 0.00005310636639698 Eth | 0.02719126436639698 Eth | 0.027138158 | ||
| 0x34912eFC...6A031E72d | 0.003476045063623383 Eth | 0.030614203063623383 Eth | 0.027138158 | ||
| 0x3674840e...8dBF7bD5F |
0.03528670847528877 Eth
Nonce: 1120
|
0.156397896100026014 Eth
Nonce: 1121
| 0.121111187624737244 | ||
| 0x378a6549...C43944Ed4 | 0.033274953089799678 Eth | 0.060413111089799678 Eth | 0.027138158 | ||
| 0x3893F2FF...8fe5287B2 | 3.415992570837446604 Eth | 3.470268886837446604 Eth | 0.054276316 | ||
| 0x42d76341...980328e57 | 0.004694804244986531 Eth | 0.031832962244986531 Eth | 0.027138158 | ||
| 0x4E29A366...fC42c80d2 | 0.30304593196109322 Eth | 0.35732224796109322 Eth | 0.054276316 | ||
| 0x61E1C419...fe35c0643 | 0.022578275650426685 Eth | 0.049716433650426685 Eth | 0.027138158 | ||
| 0x653125A8...0fa2F19A3 | 0.004534218850168609 Eth | 0.031672376850168609 Eth | 0.027138158 | ||
| 0x7072fC60...4bAc1dEe4 | 8.173919387024707863 Eth | 8.255333861024707863 Eth | 0.081414474 | ||
| 0x72b40Caa...8B913e9fC | 5.244523110846223302 Eth | 5.298799426846223302 Eth | 0.054276316 | ||
| 0x7a6A9596...D3Defa1f2 | 2.837192232678643955 Eth | 2.891468548678643955 Eth | 0.054276316 | ||
| 0x7d6693aB...9aA068EBA | 0.005267504482901587 Eth | 0.032405662482901587 Eth | 0.027138158 | ||
| 0x84490c42...1904D8A04 | 69.214706361910523982 Eth | 69.350397150910523982 Eth | 0.135690789 | ||
| 0x8FeE92a2...1a362ACF4 | 0.003793438594002807 Eth | 0.085207912594002807 Eth | 0.081414474 | ||
| 0x9194E2d1...68eE40dE1 | 0.002301637081525677 Eth | 0.029439795081525677 Eth | 0.027138158 | ||
| 0x91c29D30...5459871D9 | 0.159811926688687929 Eth | 0.186950084688687929 Eth | 0.027138158 | ||
| 0x91d5EFD1...84AbA4228 | 0.000140079004947 Eth | 0.081554553004947 Eth | 0.081414474 | ||
| 0x9254C0fc...03Ba3d05d | 6.732750719235010644 Eth | 6.767117019528154648 Eth | 0.034366300293144004 | ||
| 0xa0d9665E...d69Fd9224 | 0.090024059127539677 Eth | 0.117162217127539677 Eth | 0.027138158 | ||
| 0xa4EC64dc...b072bF724 | 0.138330060766104261 Eth | 0.192606376766104261 Eth | 0.054276316 | ||
| 0xa949DCc3...b70c6a792 | 1.20568009537318193 Eth | 1.23281825337318193 Eth | 0.027138158 | ||
| 0xB890F264...1CF677AE9 | 39.384639484114914427 Eth | 39.520330273114914427 Eth | 0.135690789 | ||
| 0xBF680Ad4...19eadC65e | 0.080131314873148069 Eth | 0.107269472873148069 Eth | 0.027138158 | ||
| 0xC539A160...134E14bd1 | 8.252125697169114728 Eth | 6.155259391875970724 Eth | 2.096866305293144004 | ||
| 0xcc86412a...9311a49e3 | 2.361345658055769733 Eth | 2.442760132055769733 Eth | 0.081414474 | ||
| 0xcdE0398A...0eC2Ee10A | 0.004736941012730503 Eth | 0.031875099012730503 Eth | 0.027138158 | ||
| 0xCE25Fd73...33f2b0D0f | 0.006337560316207782 Eth | 0.033475718316207782 Eth | 0.027138158 | ||
| 0xD88ED837...B3cc21726 | 0.033204673490441332 Eth | 0.060342831490441332 Eth | 0.027138158 | ||
| 0xd990d64b...87F99f312 | 0.144051255329991483 Eth | 0.171189413329991483 Eth | 0.027138158 | ||
| 0xD997E882...E8Ac2b909 | 0.000673322976445577 Eth | 0.109225954976445577 Eth | 0.108552632 | ||
|
0xDAFEA492...692c98Bc5
Miner
| (Flashbots: Builder) | 1.187568431211227424 Eth | 1.188458232711227424 Eth | 0.0008898015 | |
| 0xdfE61ca7...0220F3B0b | 0.001431588258470223 Eth | 0.028569746258470223 Eth | 0.027138158 | ||
| 0xE75d7d7b...6f7Fc6E9a | 0.090627817285706947 Eth | 0.144904133285706947 Eth | 0.054276316 | ||
| 0xe88ceb8e...A25834a70 | 0.009471107886092349 Eth | 0.036609265886092349 Eth | 0.027138158 | ||
| 0xecd495c4...33CeBe2f5 | 0.013874734014881909 Eth | 0.122427366014881909 Eth | 0.108552632 | ||
| 0xefD192b6...1016bEF6c | 4.125396922205023588 Eth | 4.206811396205023588 Eth | 0.081414474 | ||
| 0xf6bf6468...0C43B66a7 | 0.097550055635180819 Eth | 0.124688213635180819 Eth | 0.027138158 | ||
| 0xfae94C4B...64A80EeA1 | 0.016487393472935967 Eth | 0.070763709472935967 Eth | 0.054276316 | ||
| 0xfd3C5b8B...3C14Ab50f | 3.345409863423671882 Eth | 3.372548021423671882 Eth | 0.027138158 |
Execution Trace
0xc539a16028b4168490dc42080c02f28134e14bd1.6a761202( )
GnosisSafe.execTransaction( to=0x88777bcCb752B20245400049021CB47b8fbCf640, value=2096866305293144004, data=0x52B0F196000000000000000000000000000000000000000000000000007A17F7D1379DC4000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000005A000000000000000000000000000000000000000000000000000000000000000290000000000000000000000000224C7FC8BC1D12DA3959C07E78646ADD7FD4DA40000000000000000000000000811E06C09F9E39B04B9896DCB498DEAF51983B800000000000000000000000014235A0DE09871A93F47C0558A837250124A27BA0000000000000000000000001B0D2D718C7DDC2955554CD8953D43F17190A0A00000000000000000000000002C393B90B7FB1926CA2AA57445F1C76B2B68FCA900000000000000000000000034912EFC0EF9D0B44ACFD38C55AF69D6A031E72D0000000000000000000000003674840E64A5B2176052D9F65A9AC7E8DBF7BD5F000000000000000000000000378A654965FACFC5B2D8156177CEF54C43944ED40000000000000000000000003893F2FF234739B39DC88E8017E97828FE5287B200000000000000000000000042D763414FEC04F3D6C0CF902CB2AE4980328E570000000000000000000000004E29A366D1C9A92D449F450CBCBD4AAFC42C80D200000000000000000000000061E1C419D68E6B7484FF05CD611B531FE35C0643000000000000000000000000653125A8C0352923FB45252D3FCAB320FA2F19A30000000000000000000000007072FC60A6C6B913D78035935E733A24BAC1DEE400000000000000000000000072B40CAA258C237C6F5947E291650808B913E9FC0000000000000000000000007A6A9596AF512A7E5B1EF331A70015CD3DEFA1F20000000000000000000000007D6693AB8B51DB8F4CD3BE2900D0F2D9AA068EBA00000000000000000000000084490C42930B6648EF28851E6698A911904D8A040000000000000000000000008FEE92A2C1A6B7EA67AD9580D9585EE1A362ACF40000000000000000000000009194E2D1B507632EB5C76B64A00041968EE40DE100000000000000000000000091C29D30090C77ECCDE977EA530D6385459871D900000000000000000000000091D5EFD15DF4C6542BC462D05C69A4984ABA4228000000000000000000000000A0D9665E163F498082CD73048DA17E7D69FD9224000000000000000000000000A4EC64DCDD70B37A587F7583EE7FEAAB072BF724000000000000000000000000A949DCC3E472A4D62795C310C419395B70C6A792000000000000000000000000B890F264B1A7591CDF9E21B3B640A741CF677AE9000000000000000000000000BF680AD4439588D92B33FF78BDFF37A19EADC65E000000000000000000000000CC86412AFB2EEFC3862D723DDEF41FE9311A49E3000000000000000000000000CDE0398A96741B19CCB4C8EDFC96F630EC2EE10A000000000000000000000000CE25FD73AFCC36CB33916BA07732C9E33F2B0D0F000000000000000000000000D88ED83743A1F04BD6988094DD049A6B3CC21726000000000000000000000000D990D64B44A46BF0DC93AE884DE96A787F99F312000000000000000000000000D997E882F387578E33AF9764351FCCEE8AC2B909000000000000000000000000DFE61CA71AA5931243DE3FB38F481180220F3B0B000000000000000000000000E75D7D7B6B8674630EADADD9F6AE1136F7FC6E9A000000000000000000000000E88CEB8EB0566551ADE8C9B398B16ADA25834A70000000000000000000000000ECD495C47DEFE203BDD25D6BC7A412033CEBE2F5000000000000000000000000EFD192B6ECCA66F3E00E3E1B498C6F91016BEF6C000000000000000000000000F6BF64685F9A44BD96DA7859785F0140C43B66A7000000000000000000000000FAE94C4B2C82F2AA2EB065DA642642764A80EEA1000000000000000000000000FD3C5B8BE7783CD90169D2E4BC920833C14AB50F000000000000000000000000000000000000000000000000000000000000002900000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000001E2120DBDA3320000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000C0D40596E5980000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000C0D40596E5980000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000001213E086258640000000000000000000000000000000000000000000000000000C0D40596E5980000000000000000000000000000000000000000000000000000C0D40596E5980000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000001E2120DBDA3320000000000000000000000000000000000000000000000000001213E086258640000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000001213E086258640000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000C0D40596E5980000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000001E2120DBDA3320000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000001213E086258640000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000606A02CB72CC000000000000000000000000000000000000000000000000000181A80B2DCB300000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000C0D40596E5980000000000000000000000000000000000000000000000000000606A02CB72CC000000000000000000000000000000000000000000000000000181A80B2DCB300000000000000000000000000000000000000000000000000001213E086258640000000000000000000000000000000000000000000000000000606A02CB72CC0000000000000000000000000000000000000000000000000000C0D40596E5980000000000000000000000000000000000000000000000000000606A02CB72CC00, operation=0, safeTxGas=0, baseGas=0, gasPrice=0, gasToken=0x0000000000000000000000000000000000000000, refundReceiver=0x0000000000000000000000000000000000000000, signatures=0x0000000000000000000000003674840E64A5B2176052D9F65A9AC7E8DBF7BD5F00000000000000000000000000000000000000000000000000000000000000000127EA37BA3F1C1FAB641FD1700AD175832A72E162BF51480C86AD9B1A9EB96FD46512791CACE1933AF0A4EC1F03345B0118C5B1CE67C76BA271CEA4788963323D1C847907E2E66D2B8209E8489AEEC454B46E5641D9470643D3AAFB5A2585F9357A2206A6DB67C6FA2A860C256259F3860EC1616812DA78D3AC9884901B0E4C4DDA1C ) => ( success=True )-
Null: 0x000...001.7df8a7ea( ) -
Null: 0x000...001.7df8a7ea( ) ETH 2.096866305293144004
0x88777bccb752b20245400049021cb47b8fbcf640.52b0f196( )- ETH 0.034366300293144004
0x9254c0fcb2faa4550b9ba582558ce1d03ba3d05d.CALL( ) - ETH 0.027138158
0x0224c7fc8bc1d12da3959c07e78646add7fd4da4.CALL( ) - ETH 0.027138158
0x0811e06c09f9e39b04b9896dcb498deaf51983b8.CALL( ) - ETH 0.027138158
0x14235a0de09871a93f47c0558a837250124a27ba.CALL( ) - ETH 0.027138158
0x1b0d2d718c7ddc2955554cd8953d43f17190a0a0.CALL( ) - ETH 0.027138158
0x2c393b90b7fb1926ca2aa57445f1c76b2b68fca9.CALL( ) - ETH 0.027138158
0x34912efc0ef9d0b44acfd38c55af69d6a031e72d.CALL( ) - ETH 0.135690789
0x3674840e64a5b2176052d9f65a9ac7e8dbf7bd5f.CALL( ) - ETH 0.027138158
0x378a654965facfc5b2d8156177cef54c43944ed4.CALL( ) - ETH 0.054276316
0x3893f2ff234739b39dc88e8017e97828fe5287b2.CALL( ) - ETH 0.027138158
0x42d763414fec04f3d6c0cf902cb2ae4980328e57.CALL( ) - ETH 0.054276316
0x4e29a366d1c9a92d449f450cbcbd4aafc42c80d2.CALL( ) - ETH 0.027138158
0x61e1c419d68e6b7484ff05cd611b531fe35c0643.CALL( ) - ETH 0.027138158
0x653125a8c0352923fb45252d3fcab320fa2f19a3.CALL( ) - ETH 0.081414474
0x7072fc60a6c6b913d78035935e733a24bac1dee4.CALL( ) - ETH 0.054276316
0x72b40caa258c237c6f5947e291650808b913e9fc.CALL( ) - ETH 0.054276316
0x7a6a9596af512a7e5b1ef331a70015cd3defa1f2.CALL( ) - ETH 0.027138158
0x7d6693ab8b51db8f4cd3be2900d0f2d9aa068eba.CALL( ) - ETH 0.135690789
0x84490c42930b6648ef28851e6698a911904d8a04.CALL( ) - ETH 0.081414474
0x8fee92a2c1a6b7ea67ad9580d9585ee1a362acf4.CALL( ) - ETH 0.027138158
0x9194e2d1b507632eb5c76b64a00041968ee40de1.CALL( ) - ETH 0.027138158
0x91c29d30090c77eccde977ea530d6385459871d9.CALL( ) - ETH 0.081414474
0x91d5efd15df4c6542bc462d05c69a4984aba4228.CALL( ) - ETH 0.027138158
0xa0d9665e163f498082cd73048da17e7d69fd9224.CALL( ) - ETH 0.054276316
0xa4ec64dcdd70b37a587f7583ee7feaab072bf724.CALL( ) - ETH 0.027138158
0xa949dcc3e472a4d62795c310c419395b70c6a792.CALL( ) - ETH 0.135690789
0xb890f264b1a7591cdf9e21b3b640a741cf677ae9.CALL( ) - ETH 0.027138158
0xbf680ad4439588d92b33ff78bdff37a19eadc65e.CALL( ) - ETH 0.081414474
0xcc86412afb2eefc3862d723ddef41fe9311a49e3.CALL( ) - ETH 0.027138158
0xcde0398a96741b19ccb4c8edfc96f630ec2ee10a.CALL( ) - ETH 0.027138158
0xce25fd73afcc36cb33916ba07732c9e33f2b0d0f.CALL( ) - ETH 0.027138158
0xd88ed83743a1f04bd6988094dd049a6b3cc21726.CALL( ) - ETH 0.027138158
0xd990d64b44a46bf0dc93ae884de96a787f99f312.CALL( ) - ETH 0.108552632
0xd997e882f387578e33af9764351fccee8ac2b909.CALL( ) - ETH 0.027138158
0xdfe61ca71aa5931243de3fb38f481180220f3b0b.CALL( ) - ETH 0.054276316
0xe75d7d7b6b8674630eadadd9f6ae1136f7fc6e9a.CALL( ) - ETH 0.027138158
0xe88ceb8eb0566551ade8c9b398b16ada25834a70.CALL( ) - ETH 0.108552632
0xecd495c47defe203bdd25d6bc7a412033cebe2f5.CALL( ) - ETH 0.081414474
0xefd192b6ecca66f3e00e3e1b498c6f91016bef6c.CALL( ) - ETH 0.027138158
0xf6bf64685f9a44bd96da7859785f0140c43b66a7.CALL( ) - ETH 0.054276316
0xfae94c4b2c82f2aa2eb065da642642764a80eea1.CALL( ) - ETH 0.027138158
0xfd3c5b8be7783cd90169d2e4bc920833c14ab50f.CALL( ) 0xc539a16028b4168490dc42080c02f28134e14bd1.CALL( )-
GnosisSafe.DELEGATECALL( )
-
- ETH 0.034366300293144004
-
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
import "./base/ModuleManager.sol";
import "./base/OwnerManager.sol";
import "./base/FallbackManager.sol";
import "./base/GuardManager.sol";
import "./common/EtherPaymentFallback.sol";
import "./common/Singleton.sol";
import "./common/SignatureDecoder.sol";
import "./common/SecuredTokenTransfer.sol";
import "./common/StorageAccessible.sol";
import "./interfaces/ISignatureValidator.sol";
import "./external/GnosisSafeMath.sol";
/// @title Gnosis Safe - A multisignature wallet with support for confirmations using signed messages based on ERC191.
/// @author Stefan George - <stefan@gnosis.io>
/// @author Richard Meissner - <richard@gnosis.io>
contract GnosisSafe is
EtherPaymentFallback,
Singleton,
ModuleManager,
OwnerManager,
SignatureDecoder,
SecuredTokenTransfer,
ISignatureValidatorConstants,
FallbackManager,
StorageAccessible,
GuardManager
{
using GnosisSafeMath for uint256;
string public constant VERSION = "1.3.0";
// keccak256(
// "EIP712Domain(uint256 chainId,address verifyingContract)"
// );
bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218;
// keccak256(
// "SafeTx(address to,uint256 value,bytes data,uint8 operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address refundReceiver,uint256 nonce)"
// );
bytes32 private constant SAFE_TX_TYPEHASH = 0xbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d8;
event SafeSetup(address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler);
event ApproveHash(bytes32 indexed approvedHash, address indexed owner);
event SignMsg(bytes32 indexed msgHash);
event ExecutionFailure(bytes32 txHash, uint256 payment);
event ExecutionSuccess(bytes32 txHash, uint256 payment);
uint256 public nonce;
bytes32 private _deprecatedDomainSeparator;
// Mapping to keep track of all message hashes that have been approve by ALL REQUIRED owners
mapping(bytes32 => uint256) public signedMessages;
// Mapping to keep track of all hashes (message or transaction) that have been approve by ANY owners
mapping(address => mapping(bytes32 => uint256)) public approvedHashes;
// This constructor ensures that this contract can only be used as a master copy for Proxy contracts
constructor() {
// By setting the threshold it is not possible to call setup anymore,
// so we create a Safe with 0 owners and threshold 1.
// This is an unusable Safe, perfect for the singleton
threshold = 1;
}
/// @dev Setup function sets initial storage of contract.
/// @param _owners List of Safe owners.
/// @param _threshold Number of required confirmations for a Safe transaction.
/// @param to Contract address for optional delegate call.
/// @param data Data payload for optional delegate call.
/// @param fallbackHandler Handler for fallback calls to this contract
/// @param paymentToken Token that should be used for the payment (0 is ETH)
/// @param payment Value that should be paid
/// @param paymentReceiver Adddress that should receive the payment (or 0 if tx.origin)
function setup(
address[] calldata _owners,
uint256 _threshold,
address to,
bytes calldata data,
address fallbackHandler,
address paymentToken,
uint256 payment,
address payable paymentReceiver
) external {
// setupOwners checks if the Threshold is already set, therefore preventing that this method is called twice
setupOwners(_owners, _threshold);
if (fallbackHandler != address(0)) internalSetFallbackHandler(fallbackHandler);
// As setupOwners can only be called if the contract has not been initialized we don't need a check for setupModules
setupModules(to, data);
if (payment > 0) {
// To avoid running into issues with EIP-170 we reuse the handlePayment function (to avoid adjusting code of that has been verified we do not adjust the method itself)
// baseGas = 0, gasPrice = 1 and gas = payment => amount = (payment + 0) * 1 = payment
handlePayment(payment, 0, 1, paymentToken, paymentReceiver);
}
emit SafeSetup(msg.sender, _owners, _threshold, to, fallbackHandler);
}
/// @dev Allows to execute a Safe transaction confirmed by required number of owners and then pays the account that submitted the transaction.
/// Note: The fees are always transferred, even if the user transaction fails.
/// @param to Destination address of Safe transaction.
/// @param value Ether value of Safe transaction.
/// @param data Data payload of Safe transaction.
/// @param operation Operation type of Safe transaction.
/// @param safeTxGas Gas that should be used for the Safe transaction.
/// @param baseGas Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)
/// @param gasPrice Gas price that should be used for the payment calculation.
/// @param gasToken Token address (or 0 if ETH) that is used for the payment.
/// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
/// @param signatures Packed signature data ({bytes32 r}{bytes32 s}{uint8 v})
function execTransaction(
address to,
uint256 value,
bytes calldata data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address payable refundReceiver,
bytes memory signatures
) public payable virtual returns (bool success) {
bytes32 txHash;
// Use scope here to limit variable lifetime and prevent `stack too deep` errors
{
bytes memory txHashData =
encodeTransactionData(
// Transaction info
to,
value,
data,
operation,
safeTxGas,
// Payment info
baseGas,
gasPrice,
gasToken,
refundReceiver,
// Signature info
nonce
);
// Increase nonce and execute transaction.
nonce++;
txHash = keccak256(txHashData);
checkSignatures(txHash, txHashData, signatures);
}
address guard = getGuard();
{
if (guard != address(0)) {
Guard(guard).checkTransaction(
// Transaction info
to,
value,
data,
operation,
safeTxGas,
// Payment info
baseGas,
gasPrice,
gasToken,
refundReceiver,
// Signature info
signatures,
msg.sender
);
}
}
// We require some gas to emit the events (at least 2500) after the execution and some to perform code until the execution (500)
// We also include the 1/64 in the check that is not send along with a call to counteract potential shortings because of EIP-150
require(gasleft() >= ((safeTxGas * 64) / 63).max(safeTxGas + 2500) + 500, "GS010");
// Use scope here to limit variable lifetime and prevent `stack too deep` errors
{
uint256 gasUsed = gasleft();
// If the gasPrice is 0 we assume that nearly all available gas can be used (it is always more than safeTxGas)
// We only substract 2500 (compared to the 3000 before) to ensure that the amount passed is still higher than safeTxGas
success = execute(to, value, data, operation, gasPrice == 0 ? (gasleft() - 2500) : safeTxGas);
gasUsed = gasUsed.sub(gasleft());
// If no safeTxGas and no gasPrice was set (e.g. both are 0), then the internal tx is required to be successful
// This makes it possible to use `estimateGas` without issues, as it searches for the minimum gas where the tx doesn't revert
require(success || safeTxGas != 0 || gasPrice != 0, "GS013");
// We transfer the calculated tx costs to the tx.origin to avoid sending it to intermediate contracts that have made calls
uint256 payment = 0;
if (gasPrice > 0) {
payment = handlePayment(gasUsed, baseGas, gasPrice, gasToken, refundReceiver);
}
if (success) emit ExecutionSuccess(txHash, payment);
else emit ExecutionFailure(txHash, payment);
}
{
if (guard != address(0)) {
Guard(guard).checkAfterExecution(txHash, success);
}
}
}
function handlePayment(
uint256 gasUsed,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address payable refundReceiver
) private returns (uint256 payment) {
// solhint-disable-next-line avoid-tx-origin
address payable receiver = refundReceiver == address(0) ? payable(tx.origin) : refundReceiver;
if (gasToken == address(0)) {
// For ETH we will only adjust the gas price to not be higher than the actual used gas price
payment = gasUsed.add(baseGas).mul(gasPrice < tx.gasprice ? gasPrice : tx.gasprice);
require(receiver.send(payment), "GS011");
} else {
payment = gasUsed.add(baseGas).mul(gasPrice);
require(transferToken(gasToken, receiver, payment), "GS012");
}
}
/**
* @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
* @param dataHash Hash of the data (could be either a message hash or transaction hash)
* @param data That should be signed (this is passed to an external validator contract)
* @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
*/
function checkSignatures(
bytes32 dataHash,
bytes memory data,
bytes memory signatures
) public view {
// Load threshold to avoid multiple storage loads
uint256 _threshold = threshold;
// Check that a threshold is set
require(_threshold > 0, "GS001");
checkNSignatures(dataHash, data, signatures, _threshold);
}
/**
* @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
* @param dataHash Hash of the data (could be either a message hash or transaction hash)
* @param data That should be signed (this is passed to an external validator contract)
* @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
* @param requiredSignatures Amount of required valid signatures.
*/
function checkNSignatures(
bytes32 dataHash,
bytes memory data,
bytes memory signatures,
uint256 requiredSignatures
) public view {
// Check that the provided signature data is not too short
require(signatures.length >= requiredSignatures.mul(65), "GS020");
// There cannot be an owner with address 0.
address lastOwner = address(0);
address currentOwner;
uint8 v;
bytes32 r;
bytes32 s;
uint256 i;
for (i = 0; i < requiredSignatures; i++) {
(v, r, s) = signatureSplit(signatures, i);
if (v == 0) {
// If v is 0 then it is a contract signature
// When handling contract signatures the address of the contract is encoded into r
currentOwner = address(uint160(uint256(r)));
// Check that signature data pointer (s) is not pointing inside the static part of the signatures bytes
// This check is not completely accurate, since it is possible that more signatures than the threshold are send.
// Here we only check that the pointer is not pointing inside the part that is being processed
require(uint256(s) >= requiredSignatures.mul(65), "GS021");
// Check that signature data pointer (s) is in bounds (points to the length of data -> 32 bytes)
require(uint256(s).add(32) <= signatures.length, "GS022");
// Check if the contract signature is in bounds: start of data is s + 32 and end is start + signature length
uint256 contractSignatureLen;
// solhint-disable-next-line no-inline-assembly
assembly {
contractSignatureLen := mload(add(add(signatures, s), 0x20))
}
require(uint256(s).add(32).add(contractSignatureLen) <= signatures.length, "GS023");
// Check signature
bytes memory contractSignature;
// solhint-disable-next-line no-inline-assembly
assembly {
// The signature data for contract signatures is appended to the concatenated signatures and the offset is stored in s
contractSignature := add(add(signatures, s), 0x20)
}
require(ISignatureValidator(currentOwner).isValidSignature(data, contractSignature) == EIP1271_MAGIC_VALUE, "GS024");
} else if (v == 1) {
// If v is 1 then it is an approved hash
// When handling approved hashes the address of the approver is encoded into r
currentOwner = address(uint160(uint256(r)));
// Hashes are automatically approved by the sender of the message or when they have been pre-approved via a separate transaction
require(msg.sender == currentOwner || approvedHashes[currentOwner][dataHash] != 0, "GS025");
} else if (v > 30) {
// If v > 30 then default va (27,28) has been adjusted for eth_sign flow
// To support eth_sign and similar we adjust v and hash the messageHash with the Ethereum message prefix before applying ecrecover
currentOwner = ecrecover(keccak256(abi.encodePacked("\\x19Ethereum Signed Message:\
32", dataHash)), v - 4, r, s);
} else {
// Default is the ecrecover flow with the provided data hash
// Use ecrecover with the messageHash for EOA signatures
currentOwner = ecrecover(dataHash, v, r, s);
}
require(currentOwner > lastOwner && owners[currentOwner] != address(0) && currentOwner != SENTINEL_OWNERS, "GS026");
lastOwner = currentOwner;
}
}
/// @dev Allows to estimate a Safe transaction.
/// This method is only meant for estimation purpose, therefore the call will always revert and encode the result in the revert data.
/// Since the `estimateGas` function includes refunds, call this method to get an estimated of the costs that are deducted from the safe with `execTransaction`
/// @param to Destination address of Safe transaction.
/// @param value Ether value of Safe transaction.
/// @param data Data payload of Safe transaction.
/// @param operation Operation type of Safe transaction.
/// @return Estimate without refunds and overhead fees (base transaction and payload data gas costs).
/// @notice Deprecated in favor of common/StorageAccessible.sol and will be removed in next version.
function requiredTxGas(
address to,
uint256 value,
bytes calldata data,
Enum.Operation operation
) external returns (uint256) {
uint256 startGas = gasleft();
// We don't provide an error message here, as we use it to return the estimate
require(execute(to, value, data, operation, gasleft()));
uint256 requiredGas = startGas - gasleft();
// Convert response to string and return via error message
revert(string(abi.encodePacked(requiredGas)));
}
/**
* @dev Marks a hash as approved. This can be used to validate a hash that is used by a signature.
* @param hashToApprove The hash that should be marked as approved for signatures that are verified by this contract.
*/
function approveHash(bytes32 hashToApprove) external {
require(owners[msg.sender] != address(0), "GS030");
approvedHashes[msg.sender][hashToApprove] = 1;
emit ApproveHash(hashToApprove, msg.sender);
}
/// @dev Returns the chain id used by this contract.
function getChainId() public view returns (uint256) {
uint256 id;
// solhint-disable-next-line no-inline-assembly
assembly {
id := chainid()
}
return id;
}
function domainSeparator() public view returns (bytes32) {
return keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, getChainId(), this));
}
/// @dev Returns the bytes that are hashed to be signed by owners.
/// @param to Destination address.
/// @param value Ether value.
/// @param data Data payload.
/// @param operation Operation type.
/// @param safeTxGas Gas that should be used for the safe transaction.
/// @param baseGas Gas costs for that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)
/// @param gasPrice Maximum gas price that should be used for this transaction.
/// @param gasToken Token address (or 0 if ETH) that is used for the payment.
/// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
/// @param _nonce Transaction nonce.
/// @return Transaction hash bytes.
function encodeTransactionData(
address to,
uint256 value,
bytes calldata data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address refundReceiver,
uint256 _nonce
) public view returns (bytes memory) {
bytes32 safeTxHash =
keccak256(
abi.encode(
SAFE_TX_TYPEHASH,
to,
value,
keccak256(data),
operation,
safeTxGas,
baseGas,
gasPrice,
gasToken,
refundReceiver,
_nonce
)
);
return abi.encodePacked(bytes1(0x19), bytes1(0x01), domainSeparator(), safeTxHash);
}
/// @dev Returns hash to be signed by owners.
/// @param to Destination address.
/// @param value Ether value.
/// @param data Data payload.
/// @param operation Operation type.
/// @param safeTxGas Fas that should be used for the safe transaction.
/// @param baseGas Gas costs for data used to trigger the safe transaction.
/// @param gasPrice Maximum gas price that should be used for this transaction.
/// @param gasToken Token address (or 0 if ETH) that is used for the payment.
/// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
/// @param _nonce Transaction nonce.
/// @return Transaction hash.
function getTransactionHash(
address to,
uint256 value,
bytes calldata data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address refundReceiver,
uint256 _nonce
) public view returns (bytes32) {
return keccak256(encodeTransactionData(to, value, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, _nonce));
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
import "../common/Enum.sol";
/// @title Executor - A contract that can execute transactions
/// @author Richard Meissner - <richard@gnosis.pm>
contract Executor {
function execute(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
uint256 txGas
) internal returns (bool success) {
if (operation == Enum.Operation.DelegateCall) {
// solhint-disable-next-line no-inline-assembly
assembly {
success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)
}
} else {
// solhint-disable-next-line no-inline-assembly
assembly {
success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)
}
}
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
import "../common/SelfAuthorized.sol";
/// @title Fallback Manager - A contract that manages fallback calls made to this contract
/// @author Richard Meissner - <richard@gnosis.pm>
contract FallbackManager is SelfAuthorized {
event ChangedFallbackHandler(address handler);
// keccak256("fallback_manager.handler.address")
bytes32 internal constant FALLBACK_HANDLER_STORAGE_SLOT = 0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5;
function internalSetFallbackHandler(address handler) internal {
bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(slot, handler)
}
}
/// @dev Allows to add a contract to handle fallback calls.
/// Only fallback calls without value and with data will be forwarded.
/// This can only be done via a Safe transaction.
/// @param handler contract to handle fallbacks calls.
function setFallbackHandler(address handler) public authorized {
internalSetFallbackHandler(handler);
emit ChangedFallbackHandler(handler);
}
// solhint-disable-next-line payable-fallback,no-complex-fallback
fallback() external {
bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
let handler := sload(slot)
if iszero(handler) {
return(0, 0)
}
calldatacopy(0, 0, calldatasize())
// The msg.sender address is shifted to the left by 12 bytes to remove the padding
// Then the address without padding is stored right after the calldata
mstore(calldatasize(), shl(96, caller()))
// Add 20 bytes for the address appended add the end
let success := call(gas(), handler, 0, 0, add(calldatasize(), 20), 0, 0)
returndatacopy(0, 0, returndatasize())
if iszero(success) {
revert(0, returndatasize())
}
return(0, returndatasize())
}
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
import "../common/Enum.sol";
import "../common/SelfAuthorized.sol";
interface Guard {
function checkTransaction(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address payable refundReceiver,
bytes memory signatures,
address msgSender
) external;
function checkAfterExecution(bytes32 txHash, bool success) external;
}
/// @title Fallback Manager - A contract that manages fallback calls made to this contract
/// @author Richard Meissner - <richard@gnosis.pm>
contract GuardManager is SelfAuthorized {
event ChangedGuard(address guard);
// keccak256("guard_manager.guard.address")
bytes32 internal constant GUARD_STORAGE_SLOT = 0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8;
/// @dev Set a guard that checks transactions before execution
/// @param guard The address of the guard to be used or the 0 address to disable the guard
function setGuard(address guard) external authorized {
bytes32 slot = GUARD_STORAGE_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(slot, guard)
}
emit ChangedGuard(guard);
}
function getGuard() internal view returns (address guard) {
bytes32 slot = GUARD_STORAGE_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
guard := sload(slot)
}
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
import "../common/Enum.sol";
import "../common/SelfAuthorized.sol";
import "./Executor.sol";
/// @title Module Manager - A contract that manages modules that can execute transactions via this contract
/// @author Stefan George - <stefan@gnosis.pm>
/// @author Richard Meissner - <richard@gnosis.pm>
contract ModuleManager is SelfAuthorized, Executor {
event EnabledModule(address module);
event DisabledModule(address module);
event ExecutionFromModuleSuccess(address indexed module);
event ExecutionFromModuleFailure(address indexed module);
address internal constant SENTINEL_MODULES = address(0x1);
mapping(address => address) internal modules;
function setupModules(address to, bytes memory data) internal {
require(modules[SENTINEL_MODULES] == address(0), "GS100");
modules[SENTINEL_MODULES] = SENTINEL_MODULES;
if (to != address(0))
// Setup has to complete successfully or transaction fails.
require(execute(to, 0, data, Enum.Operation.DelegateCall, gasleft()), "GS000");
}
/// @dev Allows to add a module to the whitelist.
/// This can only be done via a Safe transaction.
/// @notice Enables the module `module` for the Safe.
/// @param module Module to be whitelisted.
function enableModule(address module) public authorized {
// Module address cannot be null or sentinel.
require(module != address(0) && module != SENTINEL_MODULES, "GS101");
// Module cannot be added twice.
require(modules[module] == address(0), "GS102");
modules[module] = modules[SENTINEL_MODULES];
modules[SENTINEL_MODULES] = module;
emit EnabledModule(module);
}
/// @dev Allows to remove a module from the whitelist.
/// This can only be done via a Safe transaction.
/// @notice Disables the module `module` for the Safe.
/// @param prevModule Module that pointed to the module to be removed in the linked list
/// @param module Module to be removed.
function disableModule(address prevModule, address module) public authorized {
// Validate module address and check that it corresponds to module index.
require(module != address(0) && module != SENTINEL_MODULES, "GS101");
require(modules[prevModule] == module, "GS103");
modules[prevModule] = modules[module];
modules[module] = address(0);
emit DisabledModule(module);
}
/// @dev Allows a Module to execute a Safe transaction without any further confirmations.
/// @param to Destination address of module transaction.
/// @param value Ether value of module transaction.
/// @param data Data payload of module transaction.
/// @param operation Operation type of module transaction.
function execTransactionFromModule(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation
) public virtual returns (bool success) {
// Only whitelisted modules are allowed.
require(msg.sender != SENTINEL_MODULES && modules[msg.sender] != address(0), "GS104");
// Execute transaction without further confirmations.
success = execute(to, value, data, operation, gasleft());
if (success) emit ExecutionFromModuleSuccess(msg.sender);
else emit ExecutionFromModuleFailure(msg.sender);
}
/// @dev Allows a Module to execute a Safe transaction without any further confirmations and return data
/// @param to Destination address of module transaction.
/// @param value Ether value of module transaction.
/// @param data Data payload of module transaction.
/// @param operation Operation type of module transaction.
function execTransactionFromModuleReturnData(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation
) public returns (bool success, bytes memory returnData) {
success = execTransactionFromModule(to, value, data, operation);
// solhint-disable-next-line no-inline-assembly
assembly {
// Load free memory location
let ptr := mload(0x40)
// We allocate memory for the return data by setting the free memory location to
// current free memory location + data size + 32 bytes for data size value
mstore(0x40, add(ptr, add(returndatasize(), 0x20)))
// Store the size
mstore(ptr, returndatasize())
// Store the data
returndatacopy(add(ptr, 0x20), 0, returndatasize())
// Point the return data to the correct memory location
returnData := ptr
}
}
/// @dev Returns if an module is enabled
/// @return True if the module is enabled
function isModuleEnabled(address module) public view returns (bool) {
return SENTINEL_MODULES != module && modules[module] != address(0);
}
/// @dev Returns array of modules.
/// @param start Start of the page.
/// @param pageSize Maximum number of modules that should be returned.
/// @return array Array of modules.
/// @return next Start of the next page.
function getModulesPaginated(address start, uint256 pageSize) external view returns (address[] memory array, address next) {
// Init array with max page size
array = new address[](pageSize);
// Populate return array
uint256 moduleCount = 0;
address currentModule = modules[start];
while (currentModule != address(0x0) && currentModule != SENTINEL_MODULES && moduleCount < pageSize) {
array[moduleCount] = currentModule;
currentModule = modules[currentModule];
moduleCount++;
}
next = currentModule;
// Set correct size of returned array
// solhint-disable-next-line no-inline-assembly
assembly {
mstore(array, moduleCount)
}
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
import "../common/SelfAuthorized.sol";
/// @title OwnerManager - Manages a set of owners and a threshold to perform actions.
/// @author Stefan George - <stefan@gnosis.pm>
/// @author Richard Meissner - <richard@gnosis.pm>
contract OwnerManager is SelfAuthorized {
event AddedOwner(address owner);
event RemovedOwner(address owner);
event ChangedThreshold(uint256 threshold);
address internal constant SENTINEL_OWNERS = address(0x1);
mapping(address => address) internal owners;
uint256 internal ownerCount;
uint256 internal threshold;
/// @dev Setup function sets initial storage of contract.
/// @param _owners List of Safe owners.
/// @param _threshold Number of required confirmations for a Safe transaction.
function setupOwners(address[] memory _owners, uint256 _threshold) internal {
// Threshold can only be 0 at initialization.
// Check ensures that setup function can only be called once.
require(threshold == 0, "GS200");
// Validate that threshold is smaller than number of added owners.
require(_threshold <= _owners.length, "GS201");
// There has to be at least one Safe owner.
require(_threshold >= 1, "GS202");
// Initializing Safe owners.
address currentOwner = SENTINEL_OWNERS;
for (uint256 i = 0; i < _owners.length; i++) {
// Owner address cannot be null.
address owner = _owners[i];
require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this) && currentOwner != owner, "GS203");
// No duplicate owners allowed.
require(owners[owner] == address(0), "GS204");
owners[currentOwner] = owner;
currentOwner = owner;
}
owners[currentOwner] = SENTINEL_OWNERS;
ownerCount = _owners.length;
threshold = _threshold;
}
/// @dev Allows to add a new owner to the Safe and update the threshold at the same time.
/// This can only be done via a Safe transaction.
/// @notice Adds the owner `owner` to the Safe and updates the threshold to `_threshold`.
/// @param owner New owner address.
/// @param _threshold New threshold.
function addOwnerWithThreshold(address owner, uint256 _threshold) public authorized {
// Owner address cannot be null, the sentinel or the Safe itself.
require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this), "GS203");
// No duplicate owners allowed.
require(owners[owner] == address(0), "GS204");
owners[owner] = owners[SENTINEL_OWNERS];
owners[SENTINEL_OWNERS] = owner;
ownerCount++;
emit AddedOwner(owner);
// Change threshold if threshold was changed.
if (threshold != _threshold) changeThreshold(_threshold);
}
/// @dev Allows to remove an owner from the Safe and update the threshold at the same time.
/// This can only be done via a Safe transaction.
/// @notice Removes the owner `owner` from the Safe and updates the threshold to `_threshold`.
/// @param prevOwner Owner that pointed to the owner to be removed in the linked list
/// @param owner Owner address to be removed.
/// @param _threshold New threshold.
function removeOwner(
address prevOwner,
address owner,
uint256 _threshold
) public authorized {
// Only allow to remove an owner, if threshold can still be reached.
require(ownerCount - 1 >= _threshold, "GS201");
// Validate owner address and check that it corresponds to owner index.
require(owner != address(0) && owner != SENTINEL_OWNERS, "GS203");
require(owners[prevOwner] == owner, "GS205");
owners[prevOwner] = owners[owner];
owners[owner] = address(0);
ownerCount--;
emit RemovedOwner(owner);
// Change threshold if threshold was changed.
if (threshold != _threshold) changeThreshold(_threshold);
}
/// @dev Allows to swap/replace an owner from the Safe with another address.
/// This can only be done via a Safe transaction.
/// @notice Replaces the owner `oldOwner` in the Safe with `newOwner`.
/// @param prevOwner Owner that pointed to the owner to be replaced in the linked list
/// @param oldOwner Owner address to be replaced.
/// @param newOwner New owner address.
function swapOwner(
address prevOwner,
address oldOwner,
address newOwner
) public authorized {
// Owner address cannot be null, the sentinel or the Safe itself.
require(newOwner != address(0) && newOwner != SENTINEL_OWNERS && newOwner != address(this), "GS203");
// No duplicate owners allowed.
require(owners[newOwner] == address(0), "GS204");
// Validate oldOwner address and check that it corresponds to owner index.
require(oldOwner != address(0) && oldOwner != SENTINEL_OWNERS, "GS203");
require(owners[prevOwner] == oldOwner, "GS205");
owners[newOwner] = owners[oldOwner];
owners[prevOwner] = newOwner;
owners[oldOwner] = address(0);
emit RemovedOwner(oldOwner);
emit AddedOwner(newOwner);
}
/// @dev Allows to update the number of required confirmations by Safe owners.
/// This can only be done via a Safe transaction.
/// @notice Changes the threshold of the Safe to `_threshold`.
/// @param _threshold New threshold.
function changeThreshold(uint256 _threshold) public authorized {
// Validate that threshold is smaller than number of owners.
require(_threshold <= ownerCount, "GS201");
// There has to be at least one Safe owner.
require(_threshold >= 1, "GS202");
threshold = _threshold;
emit ChangedThreshold(threshold);
}
function getThreshold() public view returns (uint256) {
return threshold;
}
function isOwner(address owner) public view returns (bool) {
return owner != SENTINEL_OWNERS && owners[owner] != address(0);
}
/// @dev Returns array of owners.
/// @return Array of Safe owners.
function getOwners() public view returns (address[] memory) {
address[] memory array = new address[](ownerCount);
// populate return array
uint256 index = 0;
address currentOwner = owners[SENTINEL_OWNERS];
while (currentOwner != SENTINEL_OWNERS) {
array[index] = currentOwner;
currentOwner = owners[currentOwner];
index++;
}
return array;
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/// @title Enum - Collection of enums
/// @author Richard Meissner - <richard@gnosis.pm>
contract Enum {
enum Operation {Call, DelegateCall}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/// @title EtherPaymentFallback - A contract that has a fallback to accept ether payments
/// @author Richard Meissner - <richard@gnosis.pm>
contract EtherPaymentFallback {
event SafeReceived(address indexed sender, uint256 value);
/// @dev Fallback function accepts Ether transactions.
receive() external payable {
emit SafeReceived(msg.sender, msg.value);
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/// @title SecuredTokenTransfer - Secure token transfer
/// @author Richard Meissner - <richard@gnosis.pm>
contract SecuredTokenTransfer {
/// @dev Transfers a token and returns if it was a success
/// @param token Token that should be transferred
/// @param receiver Receiver to whom the token should be transferred
/// @param amount The amount of tokens that should be transferred
function transferToken(
address token,
address receiver,
uint256 amount
) internal returns (bool transferred) {
// 0xa9059cbb - keccack("transfer(address,uint256)")
bytes memory data = abi.encodeWithSelector(0xa9059cbb, receiver, amount);
// solhint-disable-next-line no-inline-assembly
assembly {
// We write the return value to scratch space.
// See https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html#layout-in-memory
let success := call(sub(gas(), 10000), token, 0, add(data, 0x20), mload(data), 0, 0x20)
switch returndatasize()
case 0 {
transferred := success
}
case 0x20 {
transferred := iszero(or(iszero(success), iszero(mload(0))))
}
default {
transferred := 0
}
}
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/// @title SelfAuthorized - authorizes current contract to perform actions
/// @author Richard Meissner - <richard@gnosis.pm>
contract SelfAuthorized {
function requireSelfCall() private view {
require(msg.sender == address(this), "GS031");
}
modifier authorized() {
// This is a function call as it minimized the bytecode size
requireSelfCall();
_;
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/// @title SignatureDecoder - Decodes signatures that a encoded as bytes
/// @author Richard Meissner - <richard@gnosis.pm>
contract SignatureDecoder {
/// @dev divides bytes signature into `uint8 v, bytes32 r, bytes32 s`.
/// @notice Make sure to peform a bounds check for @param pos, to avoid out of bounds access on @param signatures
/// @param pos which signature to read. A prior bounds check of this parameter should be performed, to avoid out of bounds access
/// @param signatures concatenated rsv signatures
function signatureSplit(bytes memory signatures, uint256 pos)
internal
pure
returns (
uint8 v,
bytes32 r,
bytes32 s
)
{
// The signature format is a compact form of:
// {bytes32 r}{bytes32 s}{uint8 v}
// Compact means, uint8 is not padded to 32 bytes.
// solhint-disable-next-line no-inline-assembly
assembly {
let signaturePos := mul(0x41, pos)
r := mload(add(signatures, add(signaturePos, 0x20)))
s := mload(add(signatures, add(signaturePos, 0x40)))
// Here we are loading the last 32 bytes, including 31 bytes
// of 's'. There is no 'mload8' to do this.
//
// 'byte' is not working due to the Solidity parser, so lets
// use the second best option, 'and'
v := and(mload(add(signatures, add(signaturePos, 0x41))), 0xff)
}
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/// @title Singleton - Base for singleton contracts (should always be first super contract)
/// This contract is tightly coupled to our proxy contract (see `proxies/GnosisSafeProxy.sol`)
/// @author Richard Meissner - <richard@gnosis.io>
contract Singleton {
// singleton always needs to be first declared variable, to ensure that it is at the same location as in the Proxy contract.
// It should also always be ensured that the address is stored alone (uses a full word)
address private singleton;
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/// @title StorageAccessible - generic base contract that allows callers to access all internal storage.
/// @notice See https://github.com/gnosis/util-contracts/blob/bb5fe5fb5df6d8400998094fb1b32a178a47c3a1/contracts/StorageAccessible.sol
contract StorageAccessible {
/**
* @dev Reads `length` bytes of storage in the currents contract
* @param offset - the offset in the current contract's storage in words to start reading from
* @param length - the number of words (32 bytes) of data to read
* @return the bytes that were read.
*/
function getStorageAt(uint256 offset, uint256 length) public view returns (bytes memory) {
bytes memory result = new bytes(length * 32);
for (uint256 index = 0; index < length; index++) {
// solhint-disable-next-line no-inline-assembly
assembly {
let word := sload(add(offset, index))
mstore(add(add(result, 0x20), mul(index, 0x20)), word)
}
}
return result;
}
/**
* @dev Performs a delegetecall on a targetContract in the context of self.
* Internally reverts execution to avoid side effects (making it static).
*
* This method reverts with data equal to `abi.encode(bool(success), bytes(response))`.
* Specifically, the `returndata` after a call to this method will be:
* `success:bool || response.length:uint256 || response:bytes`.
*
* @param targetContract Address of the contract containing the code to execute.
* @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).
*/
function simulateAndRevert(address targetContract, bytes memory calldataPayload) external {
// solhint-disable-next-line no-inline-assembly
assembly {
let success := delegatecall(gas(), targetContract, add(calldataPayload, 0x20), mload(calldataPayload), 0, 0)
mstore(0x00, success)
mstore(0x20, returndatasize())
returndatacopy(0x40, 0, returndatasize())
revert(0, add(returndatasize(), 0x40))
}
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/**
* @title GnosisSafeMath
* @dev Math operations with safety checks that revert on error
* Renamed from SafeMath to GnosisSafeMath to avoid conflicts
* TODO: remove once open zeppelin update to solc 0.5.0
*/
library GnosisSafeMath {
/**
* @dev Multiplies two numbers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two numbers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
}
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
contract ISignatureValidatorConstants {
// bytes4(keccak256("isValidSignature(bytes,bytes)")
bytes4 internal constant EIP1271_MAGIC_VALUE = 0x20c13b0b;
}
abstract contract ISignatureValidator is ISignatureValidatorConstants {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param _data Arbitrary length data signed on the behalf of address(this)
* @param _signature Signature byte array associated with _data
*
* MUST return the bytes4 magic value 0x20c13b0b when function passes.
* MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
* MUST allow external calls
*/
function isValidSignature(bytes memory _data, bytes memory _signature) public view virtual returns (bytes4);
}