ETH Price: $2,265.98 (+7.48%)

Transaction Decoder

Block:
12696063 at Jun-24-2021 09:34:56 AM +UTC
Transaction Fee:
0.002956856 ETH $6.70
Gas Used:
211,204 Gas / 14 Gwei

Emitted Events:

92 MarsToken.Transfer( from=[Sender] 0xbbd8d63a4c55a4f89b0d242d693c125a521622c5, to=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, value=1275832225133381869678631 )
93 MarsToken.Approval( owner=[Sender] 0xbbd8d63a4c55a4f89b0d242d693c125a521622c5, spender=[Receiver] AggregationRouterV3, value=115792089237316195423570985008687907853269984665640562763625358874531259961304 )
94 MarsToken.Transfer( from=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, to=UniswapV2Pair, value=612399468064023297445742 )
95 TetherToken.Transfer( from=UniswapV2Pair, to=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, value=8860446008 )
96 UniswapV2Pair.Sync( reserve0=17901974751483578504717678, reserve1=250905363665 )
97 UniswapV2Pair.Swap( sender=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, amount0In=612399468064023297445742, amount1In=0, amount0Out=0, amount1Out=8860446008, to=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626 )
98 MarsToken.Transfer( from=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, to=UniswapV2Pair, value=663432757069358572232889 )
99 TetherToken.Transfer( from=UniswapV2Pair, to=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, value=9541505076 )
100 UniswapV2Pair.Sync( reserve0=21590516299419313530596840, reserve1=301879432130 )
101 UniswapV2Pair.Swap( sender=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, amount0In=663432757069358572232889, amount1In=0, amount0Out=0, amount1Out=9541505076, to=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626 )
102 TetherToken.Transfer( from=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, to=[Sender] 0xbbd8d63a4c55a4f89b0d242d693c125a521622c5, value=18401951084 )
103 AggregationRouterV3.Swapped( sender=[Sender] 0xbbd8d63a4c55a4f89b0d242d693c125a521622c5, srcToken=MarsToken, dstToken=[Receiver] TetherToken, dstReceiver=[Sender] 0xbbd8d63a4c55a4f89b0d242d693c125a521622c5, spentAmount=1275832225133381869678631, returnAmount=18401951084 )
104 ChiToken.Transfer( from=[Sender] 0xbbd8d63a4c55a4f89b0d242d693c125a521622c5, to=0x0000000000000000000000000000000000000000, value=8 )
105 ChiToken.Approval( owner=[Sender] 0xbbd8d63a4c55a4f89b0d242d693c125a521622c5, spender=[Receiver] AggregationRouterV3, value=115792089237316195423570985008687907853269984665640564039457584007913129639909 )

Account State Difference:

  Address   Before After State Difference Code
0x00000000...b0eF1fA1c
0x54bcf494...284F17fc9
0x58c8b8c9...17634bA91
0 Eth
Nonce: 0
0 Eth
Nonce: 0
From: 0 To: 0
0x64b91b92...dB650d089
0x66C0DDEd...10b4d70B7
0x73E641DA...1170a4B7b
0 Eth
Nonce: 0
0 Eth
Nonce: 0
From: 0 To: 0
0x7Ec0E5cF...3A23bDA2C
0 Eth
Nonce: 0
0 Eth
Nonce: 0
From: 0 To: 0
0x94b13216...00d05837B
0 Eth
Nonce: 0
0 Eth
Nonce: 0
From: 0 To: 0
0xACa9b0d4...651BF4Dd5
0 Eth
Nonce: 0
0 Eth
Nonce: 0
From: 0 To: 0
0xbbD8d63A...A521622c5
2.425413898112666698 Eth
Nonce: 147
2.422457042112666698 Eth
Nonce: 148
0.002956856
0xce1bAc80...7fe230ff5
0 Eth
Nonce: 0
0 Eth
Nonce: 0
From: 0 To: 0
0xdAC17F95...13D831ec7
0xf03Fb208...2aDC85C6d
0 Eth
Nonce: 0
0 Eth
Nonce: 0
From: 0 To: 0
14.222579143800489992 Eth14.225535999800489992 Eth0.002956856
0xFb4a482f...781369fA0
0 Eth
Nonce: 0
0 Eth
Nonce: 0
From: 0 To: 0

Execution Trace

AggregationRouterV3.discountedSwap( caller=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, desc=[{name:srcToken, type:address, order:1, indexed:false, value:0x66C0DDEd8433c9EA86C8cf91237B14e10b4d70B7, valueString:0x66C0DDEd8433c9EA86C8cf91237B14e10b4d70B7}, {name:dstToken, type:address, order:2, indexed:false, value:0xdAC17F958D2ee523a2206206994597C13D831ec7, valueString:0xdAC17F958D2ee523a2206206994597C13D831ec7}, {name:srcReceiver, type:address, order:3, indexed:false, value:0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, valueString:0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626}, {name:dstReceiver, type:address, order:4, indexed:false, value:0xbbD8d63A4c55a4F89B0D242d693C125A521622c5, valueString:0xbbD8d63A4c55a4F89B0D242d693C125A521622c5}, {name:amount, type:uint256, order:5, indexed:false, value:1275832225133381869678631, valueString:1275832225133381869678631}, {name:minReturnAmount, type:uint256, order:6, indexed:false, value:17849892551, valueString:17849892551}, {name:flags, type:uint256, order:7, indexed:false, value:12, valueString:12}, {name:permit, type:bytes, order:8, indexed:false, value:0x, valueString:0x}], data=0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000C00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000006E000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000B60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001A4B3AF37C00000000000000000000000000000000000000000000000000000000000000080800000000000000000000000000000000000000000000000000000000000004400000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B7000000000000000000000000000000F0000000000000000000000000000001F400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064D1660F9900000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B700000000000000000000000054BCF4948E32A8706C286416E3CED37284F17FC900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000A4B757FED600000000000000000000000054BCF4948E32A8706C286416E3CED37284F17FC900000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B7000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC70000000000000000002DC6C0FD3DFB524B2DA40C8A6D703C62BE36B5D8540626000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001A4B3AF37C00000000000000000000000000000000000000000000000000000000000000080800000000000000000000000000000000000000000000000000000000000004400000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B7000000000000000000000000000001040000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064D1660F9900000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B700000000000000000000000064B91B92240BC1901855DD55AE632ADDB650D08900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000A4B757FED600000000000000000000000064B91B92240BC1901855DD55AE632ADDB650D08900000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B7000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC70000000000000000002DC6C0FD3DFB524B2DA40C8A6D703C62BE36B5D8540626000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002647F8FE7A000000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000044000000000000000000000000FD3DFB524B2DA40C8A6D703C62BE36B5D854062600000000000000000000000000000000000000000000000000000000000001E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000A405971224000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000007A120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004470BDB947000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC70000000000000000000000000000000000000000000000000000000448D77D6C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001A4B3AF37C000000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000044000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC7000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064D1660F99000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC7000000000000000000000000BBD8D63A4C55A4F89B0D242D693C125A521622C500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ) => ( returnAmount=18401951084, gasLeft=71118, chiSpent=8 )
  • AggregationRouterV3.swap( caller=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, desc=[{name:srcToken, type:address, order:1, indexed:false, value:0x66C0DDEd8433c9EA86C8cf91237B14e10b4d70B7, valueString:0x66C0DDEd8433c9EA86C8cf91237B14e10b4d70B7}, {name:dstToken, type:address, order:2, indexed:false, value:0xdAC17F958D2ee523a2206206994597C13D831ec7, valueString:0xdAC17F958D2ee523a2206206994597C13D831ec7}, {name:srcReceiver, type:address, order:3, indexed:false, value:0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, valueString:0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626}, {name:dstReceiver, type:address, order:4, indexed:false, value:0xbbD8d63A4c55a4F89B0D242d693C125A521622c5, valueString:0xbbD8d63A4c55a4F89B0D242d693C125A521622c5}, {name:amount, type:uint256, order:5, indexed:false, value:1275832225133381869678631, valueString:1275832225133381869678631}, {name:minReturnAmount, type:uint256, order:6, indexed:false, value:17849892551, valueString:17849892551}, {name:flags, type:uint256, order:7, indexed:false, value:12, valueString:12}, {name:permit, type:bytes, order:8, indexed:false, value:0x, valueString:0x}], data=0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000C00000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000006E000000000000000000000000000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000B60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001A4B3AF37C00000000000000000000000000000000000000000000000000000000000000080800000000000000000000000000000000000000000000000000000000000004400000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B7000000000000000000000000000000F0000000000000000000000000000001F400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064D1660F9900000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B700000000000000000000000054BCF4948E32A8706C286416E3CED37284F17FC900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000A4B757FED600000000000000000000000054BCF4948E32A8706C286416E3CED37284F17FC900000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B7000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC70000000000000000002DC6C0FD3DFB524B2DA40C8A6D703C62BE36B5D8540626000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001A4B3AF37C00000000000000000000000000000000000000000000000000000000000000080800000000000000000000000000000000000000000000000000000000000004400000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B7000000000000000000000000000001040000000000000000000000000000010400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064D1660F9900000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B700000000000000000000000064B91B92240BC1901855DD55AE632ADDB650D08900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000A4B757FED600000000000000000000000064B91B92240BC1901855DD55AE632ADDB650D08900000000000000000000000066C0DDED8433C9EA86C8CF91237B14E10B4D70B7000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC70000000000000000002DC6C0FD3DFB524B2DA40C8A6D703C62BE36B5D8540626000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000002647F8FE7A000000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000044000000000000000000000000FD3DFB524B2DA40C8A6D703C62BE36B5D854062600000000000000000000000000000000000000000000000000000000000001E0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000A405971224000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000007A120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004470BDB947000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC70000000000000000000000000000000000000000000000000000000448D77D6C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001A4B3AF37C000000000000000000000000000000000000000000000000000000000000000808000000000000000000000000000000000000000000000000000000000000044000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC7000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000064D1660F99000000000000000000000000DAC17F958D2EE523A2206206994597C13D831EC7000000000000000000000000BBD8D63A4C55A4F89B0D242D693C125A521622C500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ) => ( returnAmount=18401951084, gasLeft=154233 )
    • MarsToken.transferFrom( sender=0xbbD8d63A4c55a4F89B0D242d693C125A521622c5, recipient=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, amount=1275832225133381869678631 ) => ( True )
    • TetherToken.balanceOf( who=0xbbD8d63A4c55a4F89B0D242d693C125A521622c5 ) => ( 0 )
    • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.d9c45357( )
      • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.b3af37c0( )
        • MarsToken.balanceOf( account=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626 ) => ( 1275832225133381869678631 )
        • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.d1660f99( )
          • MarsToken.transfer( recipient=0x54bcf4948e32A8706C286416e3ced37284F17fc9, amount=612399468064023297445742 ) => ( True )
          • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.b757fed6( )
            • MarsToken.balanceOf( account=0x54bcf4948e32A8706C286416e3ced37284F17fc9 ) => ( 17901974751483578504717678 )
            • UniswapV2Pair.STATICCALL( )
            • UniswapV2Pair.swap( amount0Out=0, amount1Out=8860446008, to=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, data=0x )
              • TetherToken.transfer( _to=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, _value=8860446008 )
              • MarsToken.balanceOf( account=0x54bcf4948e32A8706C286416e3ced37284F17fc9 ) => ( 17901974751483578504717678 )
              • TetherToken.balanceOf( who=0x54bcf4948e32A8706C286416e3ced37284F17fc9 ) => ( 250905363665 )
              • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.b3af37c0( )
                • MarsToken.balanceOf( account=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626 ) => ( 663432757069358572232889 )
                • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.d1660f99( )
                  • MarsToken.transfer( recipient=0x64b91b92240bC1901855Dd55AE632addB650d089, amount=663432757069358572232889 ) => ( True )
                  • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.b757fed6( )
                    • MarsToken.balanceOf( account=0x64b91b92240bC1901855Dd55AE632addB650d089 ) => ( 21590516299419313530596840 )
                    • UniswapV2Pair.STATICCALL( )
                    • UniswapV2Pair.swap( amount0Out=0, amount1Out=9541505076, to=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, data=0x )
                      • TetherToken.transfer( _to=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626, _value=9541505076 )
                      • MarsToken.balanceOf( account=0x64b91b92240bC1901855Dd55AE632addB650d089 ) => ( 21590516299419313530596840 )
                      • TetherToken.balanceOf( who=0x64b91b92240bC1901855Dd55AE632addB650d089 ) => ( 301879432130 )
                      • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.7f8fe7a0( )
                        • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.70bdb947( )
                          • TetherToken.balanceOf( who=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626 ) => ( 18401951084 )
                          • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.05971224( )
                          • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.b3af37c0( )
                            • TetherToken.balanceOf( who=0xFD3dFB524B2dA40c8a6D703c62BE36b5D8540626 ) => ( 18401951084 )
                            • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.d1660f99( )
                              • TetherToken.transfer( _to=0xbbD8d63A4c55a4F89B0D242d693C125A521622c5, _value=18401951084 )
                              • TetherToken.balanceOf( who=0xbbD8d63A4c55a4F89B0D242d693C125A521622c5 ) => ( 18401951084 )
                              • 0xfd3dfb524b2da40c8a6d703c62be36b5d8540626.1d97832e( )
                              • ChiToken.freeFromUpTo( from=0xbbD8d63A4c55a4F89B0D242d693C125A521622c5, value=8 ) => ( 8 )
                                • 0xf03fb208cb726dd7c5f1d4199ed7f122adc85c6d.CALL( )
                                  • ChiToken.SELFDESTRUCT( )
                                  • 0x73e641da3e06e04b413c9ebb87cace01170a4b7b.CALL( )
                                    • ChiToken.SELFDESTRUCT( )
                                    • 0xaca9b0d4374cbc8aae5b50d6b108077651bf4dd5.CALL( )
                                      • ChiToken.SELFDESTRUCT( )
                                      • 0x94b13216c9e7a1168ba7834e224be0a00d05837b.CALL( )
                                        • ChiToken.SELFDESTRUCT( )
                                        • 0x7ec0e5cfac75f6a47faa65f1121fe143a23bda2c.CALL( )
                                          • ChiToken.SELFDESTRUCT( )
                                          • 0x58c8b8c94e238624aeefb13cd5351ff17634ba91.CALL( )
                                            • ChiToken.SELFDESTRUCT( )
                                            • 0xce1bac808ca9b29458fb4b023aafb387fe230ff5.CALL( )
                                              • ChiToken.SELFDESTRUCT( )
                                              • 0xfb4a482fc86a619f33c5ab9cd157b87781369fa0.CALL( )
                                                • ChiToken.SELFDESTRUCT( )
                                                  File 1 of 6: AggregationRouterV3
                                                  /*
                                                                                                             ,▄▓▓██▌   ,╓▄▄▓▓▓▓▓▓▓▓▄▄▄,,                          
                                                                                                          ,▓██▓███▓▄▓███▓╬╬╬╬╬╬╬╬╬╬╬╬╬▓███▓▄,                     
                                                                                                    ▄█   ▓██╬╣███████╬▓▀╬╬▓▓▓████████████▓█████▄,                 
                                                                                                   ▓██▌ ▓██╬╣██████╬▓▌  ██████████████████████▌╙╙▀ⁿ
                                                                                                  ▐████████╬▓████▓▓█╨ ▄ ╟█████████▓▓╬╬╬╬╬▓▓█████▓▄
                                                                                    └▀▓▓▄╓        ╟█▓╣█████▓██████▀ ╓█▌ ███████▓▓▓▓▓╬╬╬╬╬╬╬╬╬╬╬╬▓██▓▄
                                                                                       └▀████▓▄╥  ▐██╬╬██████████╙ Æ▀─ ▓███▀╚╠╬╩▀▀███████▓▓╬╬╬╬╬╬╬╬╬██▄
                                                                                          └▀██▓▀▀█████▓╬▓██████▀     ▄█████▒╠"      └╙▓██████▓╬╬╬╬╬╬╬╬██▄
                                                                                             └▀██▄,└╙▀▀████▌└╙    ^"▀╙╙╙"╙██      @▄    ╙▀███████╬╬╬╬╬╬╬██µ
                                                                                                └▀██▓▄, ██▌       ╒       ╙█▓     ]▓█▓╔    ▀███████▓╬╬╬╬╬▓█▌
                                                                                                    ▀█████       ▓         ╟█▌    ]╠██▓░▒╓   ▀████████╬╬╬╬╣█▌
                                                                                                    ▐████      ╓█▀█▌      ,██▌    ╚Å███▓▒▒╠╓  ╙█████████╬╬╬╣█▌
                                                                                                    └████     ▓█░░▓█      ▀▀▀    φ▒╫████▒▒▒▒╠╓  █████████▓╬╬▓█µ
                                                                                                     ╘███µ ▌▄█▓▄▓▀`     ,▀    ,╔╠░▓██████▌╠▒▒▒φ  ██████████╬╬██
                                                                                                     ▐████µ╙▓▀`     ,▀╙,╔╔φφφ╠░▄▓███████▌░▓╙▒▒▒╠ └██╬███████╬▓█⌐
                                                                                                     ╫██ ▓▌         ▌φ▒▒░▓██████████████▌▒░▓╚▒▒▒╠ ▓██╬▓██████╣█▌
                                                                                                     ██▌           ▌╔▒▒▄████████████████▒▒▒░▌╠▒▒▒≥▐██▓╬╬███████▌
                                                                                                     ██▌      ,╓φ╠▓«▒▒▓████▀  ▀█████████▌▒▒▒╟░▒▒▒▒▐███╬╬╣████▓█▌
                                                                                                    ▐██      ╠▒▄▓▓███▓████└     ▀████████▌▒▒░▌╚▒▒▒▐███▓╬╬████ ╙▌
                                                                                                    ███  )  ╠▒░░░▒░╬████▀        └████████░▒▒░╬∩▒▒▓████╬╬╣███
                                                                                                   ▓██    ╠╠▒▒▐█▀▀▌`░╫██           ███████▒▒▒▒░▒▒½█████╬╬╣███
                                                                                                  ███ ,█▄ ╠▒▒▒╫▌,▄▀,▒╫██           ╟██████▒▒▒░╣⌠▒▓█████╬╬╣██▌
                                                                                                 ╘██µ ██` ╠▒▒░██╬φ╠▄▓██`            ██████░░▌φ╠░▓█████▓╬╬▓██
                                                                                                  ╟██  .φ╠▒░▄█▀░░▄██▀└              █████▌▒╣φ▒░▓██████╬╬╣██
                                                                                                   ▀██▄▄▄╓▄███████▀                ▐█████░▓φ▒▄███████▓╬╣██
                                                                                                     ╙▀▀▀██▀└                      ████▓▄▀φ▄▓████████╬▓█▀
                                                                                                                                  ▓███╬╩╔╣██████████▓██└
                                                                                                                                ╓████▀▄▓████████▀████▀
                                                                                                                              ,▓███████████████─]██╙
                                                                                                                           ,▄▓██████████████▀└  ╙
                                                                                                                      ,╓▄▓███████████████▀╙
                                                                                                               `"▀▀▀████████▀▀▀▀`▄███▀▀└
                                                                                                                                └└
                                                                                  
                                                                      
                                                  
                                                                      11\   11\                     11\             11\   11\            11\                                       11\       
                                                                    1111 |  \__|                    11 |            111\  11 |           11 |                                      11 |      
                                                                    \_11 |  11\ 1111111\   1111111\ 1111111\        1111\ 11 | 111111\ 111111\   11\  11\  11\  111111\   111111\  11 |  11\ 
                                                                      11 |  11 |11  __11\ 11  _____|11  __11\       11 11\11 |11  __11\\_11  _|  11 | 11 | 11 |11  __11\ 11  __11\ 11 | 11  |
                                                                      11 |  11 |11 |  11 |11 /      11 |  11 |      11 \1111 |11111111 | 11 |    11 | 11 | 11 |11 /  11 |11 |  \__|111111  / 
                                                                      11 |  11 |11 |  11 |11 |      11 |  11 |      11 |\111 |11   ____| 11 |11\ 11 | 11 | 11 |11 |  11 |11 |      11  _11<  
                                                                    111111\ 11 |11 |  11 |\1111111\ 11 |  11 |      11 | \11 |\1111111\  \1111  |\11111\1111  |\111111  |11 |      11 | \11\ 
                                                                    \______|\__|\__|  \__| \_______|\__|  \__|      \__|  \__| \_______|  \____/  \_____\____/  \______/ \__|      \__|  \__|
                                                                                                                                                                                             
                                                                                                                                                                                             
                                                                                                                                                                                             
                                                                                 111111\                                                               11\     11\                           
                                                                                11  __11\                                                              11 |    \__|                          
                                                                                11 /  11 | 111111\   111111\   111111\   111111\   111111\   111111\ 111111\   11\  111111\  1111111\        
                                                                                11111111 |11  __11\ 11  __11\ 11  __11\ 11  __11\ 11  __11\  \____11\\_11  _|  11 |11  __11\ 11  __11\       
                                                                                11  __11 |11 /  11 |11 /  11 |11 |  \__|11111111 |11 /  11 | 1111111 | 11 |    11 |11 /  11 |11 |  11 |      
                                                                                11 |  11 |11 |  11 |11 |  11 |11 |      11   ____|11 |  11 |11  __11 | 11 |11\ 11 |11 |  11 |11 |  11 |      
                                                                                11 |  11 |\1111111 |\1111111 |11 |      \1111111\ \1111111 |\1111111 | \1111  |11 |\111111  |11 |  11 |      
                                                                                \__|  \__| \____11 | \____11 |\__|       \_______| \____11 | \_______|  \____/ \__| \______/ \__|  \__|      
                                                                                          11\   11 |11\   11 |                    11\   11 |                                                 
                                                                                          \111111  |\111111  |                    \111111  |                                                 
                                                                                           \______/  \______/                      \______/                                                  
                                                                                                  1111111\                        11\                                                        
                                                                                                  11  __11\                       11 |                                                       
                                                                                                  11 |  11 | 111111\  11\   11\ 111111\    111111\   111111\                                 
                                                                                                  1111111  |11  __11\ 11 |  11 |\_11  _|  11  __11\ 11  __11\                                
                                                                                                  11  __11< 11 /  11 |11 |  11 |  11 |    11111111 |11 |  \__|                               
                                                                                                  11 |  11 |11 |  11 |11 |  11 |  11 |11\ 11   ____|11 |                                     
                                                                                                  11 |  11 |\111111  |\111111  |  \1111  |\1111111\ 11 |                                     
                                                                                                  \__|  \__| \______/  \______/    \____/  \_______|\__|                                     
                                                  */
                                                  
                                                  // File @openzeppelin/contracts/utils/Context.sol@v3.4.1
                                                  
                                                  // SPDX-License-Identifier: MIT
                                                  
                                                  pragma solidity >=0.6.0 <0.8.0;
                                                  
                                                  /*
                                                   * @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 GSN 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 payable) {
                                                          return msg.sender;
                                                      }
                                                  
                                                      function _msgData() internal view virtual returns (bytes memory) {
                                                          this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
                                                          return msg.data;
                                                      }
                                                  }
                                                  
                                                  
                                                  // File @openzeppelin/contracts/access/Ownable.sol@v3.4.1
                                                  
                                                  
                                                  
                                                  pragma solidity >=0.6.0 <0.8.0;
                                                  
                                                  /**
                                                   * @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 () internal {
                                                          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;
                                                      }
                                                  }
                                                  
                                                  
                                                  // File @openzeppelin/contracts/token/ERC20/IERC20.sol@v3.4.1
                                                  
                                                  
                                                  
                                                  pragma solidity >=0.6.0 <0.8.0;
                                                  
                                                  /**
                                                   * @dev Interface of the ERC20 standard as defined in the EIP.
                                                   */
                                                  interface IERC20 {
                                                      /**
                                                       * @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 `recipient`.
                                                       *
                                                       * Returns a boolean value indicating whether the operation succeeded.
                                                       *
                                                       * Emits a {Transfer} event.
                                                       */
                                                      function transfer(address recipient, uint256 amount) external returns (bool);
                                                  
                                                      /**
                                                       * @dev Returns the remaining number of tokens that `spender` will be
                                                       * allowed to spend on behalf of `owner` through {transferFrom}. This is
                                                       * zero by default.
                                                       *
                                                       * This value changes when {approve} or {transferFrom} are called.
                                                       */
                                                      function allowance(address owner, address spender) external view returns (uint256);
                                                  
                                                      /**
                                                       * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
                                                       *
                                                       * Returns a boolean value indicating whether the operation succeeded.
                                                       *
                                                       * IMPORTANT: Beware that changing an allowance with this method brings the risk
                                                       * that someone may use both the old and the new allowance by unfortunate
                                                       * transaction ordering. One possible solution to mitigate this race
                                                       * condition is to first reduce the spender's allowance to 0 and set the
                                                       * desired value afterwards:
                                                       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                                                       *
                                                       * Emits an {Approval} event.
                                                       */
                                                      function approve(address spender, uint256 amount) external returns (bool);
                                                  
                                                      /**
                                                       * @dev Moves `amount` tokens from `sender` to `recipient` using the
                                                       * allowance mechanism. `amount` is then deducted from the caller's
                                                       * allowance.
                                                       *
                                                       * Returns a boolean value indicating whether the operation succeeded.
                                                       *
                                                       * Emits a {Transfer} event.
                                                       */
                                                      function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
                                                  
                                                      /**
                                                       * @dev Emitted when `value` tokens are moved from one account (`from`) to
                                                       * another (`to`).
                                                       *
                                                       * Note that `value` may be zero.
                                                       */
                                                      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);
                                                  }
                                                  
                                                  
                                                  // File @openzeppelin/contracts/math/SafeMath.sol@v3.4.1
                                                  
                                                  
                                                  
                                                  pragma solidity >=0.6.0 <0.8.0;
                                                  
                                                  /**
                                                   * @dev Wrappers over Solidity's arithmetic operations with added overflow
                                                   * checks.
                                                   *
                                                   * Arithmetic operations in Solidity wrap on overflow. This can easily result
                                                   * in bugs, because programmers usually assume that an overflow raises an
                                                   * error, which is the standard behavior in high level programming languages.
                                                   * `SafeMath` restores this intuition by reverting the transaction when an
                                                   * operation overflows.
                                                   *
                                                   * Using this library instead of the unchecked operations eliminates an entire
                                                   * class of bugs, so it's recommended to use it always.
                                                   */
                                                  library SafeMath {
                                                      /**
                                                       * @dev Returns the addition of two unsigned integers, with an overflow flag.
                                                       *
                                                       * _Available since v3.4._
                                                       */
                                                      function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                                                          uint256 c = a + b;
                                                          if (c < a) return (false, 0);
                                                          return (true, c);
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the substraction of two unsigned integers, with an overflow flag.
                                                       *
                                                       * _Available since v3.4._
                                                       */
                                                      function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                                                          if (b > a) return (false, 0);
                                                          return (true, a - b);
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
                                                       *
                                                       * _Available since v3.4._
                                                       */
                                                      function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                                                          // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                                                          // benefit is lost if 'b' is also tested.
                                                          // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                                                          if (a == 0) return (true, 0);
                                                          uint256 c = a * b;
                                                          if (c / a != b) return (false, 0);
                                                          return (true, c);
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the division of two unsigned integers, with a division by zero flag.
                                                       *
                                                       * _Available since v3.4._
                                                       */
                                                      function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                                                          if (b == 0) return (false, 0);
                                                          return (true, a / b);
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
                                                       *
                                                       * _Available since v3.4._
                                                       */
                                                      function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
                                                          if (b == 0) return (false, 0);
                                                          return (true, a % b);
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the addition of two unsigned integers, reverting on
                                                       * overflow.
                                                       *
                                                       * Counterpart to Solidity's `+` operator.
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - Addition cannot overflow.
                                                       */
                                                      function add(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          uint256 c = a + b;
                                                          require(c >= a, "SafeMath: addition overflow");
                                                          return c;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the subtraction of two unsigned integers, reverting on
                                                       * overflow (when the result is negative).
                                                       *
                                                       * Counterpart to Solidity's `-` operator.
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - Subtraction cannot overflow.
                                                       */
                                                      function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          require(b <= a, "SafeMath: subtraction overflow");
                                                          return a - b;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the multiplication of two unsigned integers, reverting on
                                                       * overflow.
                                                       *
                                                       * Counterpart to Solidity's `*` operator.
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - Multiplication cannot overflow.
                                                       */
                                                      function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          if (a == 0) return 0;
                                                          uint256 c = a * b;
                                                          require(c / a == b, "SafeMath: multiplication overflow");
                                                          return c;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the integer division of two unsigned integers, reverting on
                                                       * division by zero. The result is rounded towards zero.
                                                       *
                                                       * Counterpart to Solidity's `/` operator. Note: this function uses a
                                                       * `revert` opcode (which leaves remaining gas untouched) while Solidity
                                                       * uses an invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - The divisor cannot be zero.
                                                       */
                                                      function div(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          require(b > 0, "SafeMath: division by zero");
                                                          return a / b;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
                                                       * reverting when dividing by zero.
                                                       *
                                                       * Counterpart to Solidity's `%` operator. This function uses a `revert`
                                                       * opcode (which leaves remaining gas untouched) while Solidity uses an
                                                       * invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - The divisor cannot be zero.
                                                       */
                                                      function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          require(b > 0, "SafeMath: modulo by zero");
                                                          return a % b;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
                                                       * overflow (when the result is negative).
                                                       *
                                                       * CAUTION: This function is deprecated because it requires allocating memory for the error
                                                       * message unnecessarily. For custom revert reasons use {trySub}.
                                                       *
                                                       * Counterpart to Solidity's `-` operator.
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - Subtraction cannot overflow.
                                                       */
                                                      function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                                                          require(b <= a, errorMessage);
                                                          return a - b;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the integer division of two unsigned integers, reverting with custom message on
                                                       * division by zero. The result is rounded towards zero.
                                                       *
                                                       * CAUTION: This function is deprecated because it requires allocating memory for the error
                                                       * message unnecessarily. For custom revert reasons use {tryDiv}.
                                                       *
                                                       * Counterpart to Solidity's `/` operator. Note: this function uses a
                                                       * `revert` opcode (which leaves remaining gas untouched) while Solidity
                                                       * uses an invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - The divisor cannot be zero.
                                                       */
                                                      function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                                                          require(b > 0, errorMessage);
                                                          return a / b;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
                                                       * reverting with custom message when dividing by zero.
                                                       *
                                                       * CAUTION: This function is deprecated because it requires allocating memory for the error
                                                       * message unnecessarily. For custom revert reasons use {tryMod}.
                                                       *
                                                       * Counterpart to Solidity's `%` operator. This function uses a `revert`
                                                       * opcode (which leaves remaining gas untouched) while Solidity uses an
                                                       * invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - The divisor cannot be zero.
                                                       */
                                                      function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                                                          require(b > 0, errorMessage);
                                                          return a % b;
                                                      }
                                                  }
                                                  
                                                  
                                                  // File @openzeppelin/contracts/utils/Address.sol@v3.4.1
                                                  
                                                  
                                                  
                                                  pragma solidity >=0.6.2 <0.8.0;
                                                  
                                                  /**
                                                   * @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);
                                                              }
                                                          }
                                                      }
                                                  }
                                                  
                                                  
                                                  // File @openzeppelin/contracts/token/ERC20/SafeERC20.sol@v3.4.1
                                                  
                                                  
                                                  
                                                  pragma solidity >=0.6.0 <0.8.0;
                                                  
                                                  
                                                  
                                                  /**
                                                   * @title SafeERC20
                                                   * @dev Wrappers around ERC20 operations that throw on failure (when the token
                                                   * contract returns false). Tokens that return no value (and instead revert or
                                                   * throw on failure) are also supported, non-reverting calls are assumed to be
                                                   * successful.
                                                   * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
                                                   * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
                                                   */
                                                  library SafeERC20 {
                                                      using SafeMath for uint256;
                                                      using Address for address;
                                                  
                                                      function safeTransfer(IERC20 token, address to, uint256 value) internal {
                                                          _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
                                                      }
                                                  
                                                      function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
                                                          _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
                                                      }
                                                  
                                                      /**
                                                       * @dev Deprecated. This function has issues similar to the ones found in
                                                       * {IERC20-approve}, and its usage is discouraged.
                                                       *
                                                       * Whenever possible, use {safeIncreaseAllowance} and
                                                       * {safeDecreaseAllowance} instead.
                                                       */
                                                      function safeApprove(IERC20 token, address spender, uint256 value) internal {
                                                          // safeApprove should only be called when setting an initial allowance,
                                                          // or when resetting it to zero. To increase and decrease it, use
                                                          // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
                                                          // solhint-disable-next-line max-line-length
                                                          require((value == 0) || (token.allowance(address(this), spender) == 0),
                                                              "SafeERC20: approve from non-zero to non-zero allowance"
                                                          );
                                                          _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
                                                      }
                                                  
                                                      function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                                                          uint256 newAllowance = token.allowance(address(this), spender).add(value);
                                                          _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
                                                      }
                                                  
                                                      function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
                                                          uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
                                                          _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
                                                      }
                                                  
                                                      /**
                                                       * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
                                                       * on the return value: the return value is optional (but if data is returned, it must not be false).
                                                       * @param token The token targeted by the call.
                                                       * @param data The call data (encoded using abi.encode or one of its variants).
                                                       */
                                                      function _callOptionalReturn(IERC20 token, bytes memory data) private {
                                                          // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
                                                          // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
                                                          // the target address contains contract code and also asserts for success in the low-level call.
                                                  
                                                          bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
                                                          if (returndata.length > 0) { // Return data is optional
                                                              // solhint-disable-next-line max-line-length
                                                              require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
                                                          }
                                                      }
                                                  }
                                                  
                                                  
                                                  // File contracts/helpers/UniERC20.sol
                                                  
                                                  
                                                  
                                                  pragma solidity ^0.6.12;
                                                  
                                                  
                                                  library UniERC20 {
                                                      using SafeMath for uint256;
                                                  
                                                      IERC20 private constant _ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
                                                      IERC20 private constant _ZERO_ADDRESS = IERC20(0);
                                                  
                                                      function isETH(IERC20 token) internal pure returns (bool) {
                                                          return (token == _ZERO_ADDRESS || token == _ETH_ADDRESS);
                                                      }
                                                  
                                                      function uniBalanceOf(IERC20 token, address account) internal view returns (uint256) {
                                                          if (isETH(token)) {
                                                              return account.balance;
                                                          } else {
                                                              return token.balanceOf(account);
                                                          }
                                                      }
                                                  
                                                      function uniTransfer(IERC20 token, address payable to, uint256 amount) internal {
                                                          if (amount > 0) {
                                                              if (isETH(token)) {
                                                                  to.transfer(amount);
                                                              } else {
                                                                  _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, amount));
                                                              }
                                                          }
                                                      }
                                                  
                                                      function uniApprove(IERC20 token, address to, uint256 amount) internal {
                                                          require(!isETH(token), "Approve called on ETH");
                                                  
                                                          // solhint-disable-next-line avoid-low-level-calls
                                                          (bool success, bytes memory returndata) = address(token).call(abi.encodeWithSelector(token.approve.selector, to, amount));
                                                  
                                                          if (!success || (returndata.length > 0 && !abi.decode(returndata, (bool)))) {
                                                              _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, to, 0));
                                                              _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, to, amount));
                                                          }
                                                      }
                                                  
                                                      function _callOptionalReturn(IERC20 token, bytes memory data) private {
                                                          // solhint-disable-next-line avoid-low-level-calls
                                                          (bool success, bytes memory returndata) = address(token).call(data);
                                                          require(success, "low-level call failed");
                                                  
                                                          if (returndata.length > 0) { // Return data is optional
                                                              require(abi.decode(returndata, (bool)), "ERC20 operation did not succeed");
                                                          }
                                                      }
                                                  }
                                                  
                                                  
                                                  // File contracts/interfaces/IChi.sol
                                                  
                                                  
                                                  
                                                  pragma solidity ^0.6.12;
                                                  
                                                  interface IChi is IERC20 {
                                                      function mint(uint256 value) external;
                                                      function free(uint256 value) external returns (uint256 freed);
                                                      function freeFromUpTo(address from, uint256 value) external returns (uint256 freed);
                                                  }
                                                  
                                                  
                                                  // File contracts/interfaces/IGasDiscountExtension.sol
                                                  
                                                  
                                                  
                                                  pragma solidity ^0.6.12;
                                                  
                                                  interface IGasDiscountExtension {
                                                      function calculateGas(uint256 gasUsed, uint256 flags, uint256 calldataLength) external view returns (IChi, uint256);
                                                  }
                                                  
                                                  
                                                  // File contracts/interfaces/IAggregationExecutor.sol
                                                  
                                                  
                                                  
                                                  pragma solidity ^0.6.12;
                                                  
                                                  interface IAggregationExecutor is IGasDiscountExtension {
                                                      function callBytes(bytes calldata data) external payable;  // 0xd9c45357
                                                  }
                                                  
                                                  
                                                  // File contracts/helpers/RevertReasonParser.sol
                                                  
                                                  
                                                  
                                                  pragma solidity ^0.6.12;
                                                  
                                                  
                                                  library RevertReasonParser {
                                                      function parse(bytes memory data, string memory prefix) internal pure returns (string memory) {
                                                          // https://solidity.readthedocs.io/en/latest/control-structures.html#revert
                                                          // We assume that revert reason is abi-encoded as Error(string)
                                                  
                                                          // 68 = 4-byte selector 0x08c379a0 + 32 bytes offset + 32 bytes length
                                                          if (data.length >= 68 && data[0] == "\x08" && data[1] == "\xc3" && data[2] == "\x79" && data[3] == "\xa0") {
                                                              string memory reason;
                                                              // solhint-disable no-inline-assembly
                                                              assembly {
                                                                  // 68 = 32 bytes data length + 4-byte selector + 32 bytes offset
                                                                  reason := add(data, 68)
                                                              }
                                                              /*
                                                                  revert reason is padded up to 32 bytes with ABI encoder: Error(string)
                                                                  also sometimes there is extra 32 bytes of zeros padded in the end:
                                                                  https://github.com/ethereum/solidity/issues/10170
                                                                  because of that we can't check for equality and instead check
                                                                  that string length + extra 68 bytes is less than overall data length
                                                              */
                                                              require(data.length >= 68 + bytes(reason).length, "Invalid revert reason");
                                                              return string(abi.encodePacked(prefix, "Error(", reason, ")"));
                                                          }
                                                          // 36 = 4-byte selector 0x4e487b71 + 32 bytes integer
                                                          else if (data.length == 36 && data[0] == "\x4e" && data[1] == "\x48" && data[2] == "\x7b" && data[3] == "\x71") {
                                                              uint256 code;
                                                              // solhint-disable no-inline-assembly
                                                              assembly {
                                                                  // 36 = 32 bytes data length + 4-byte selector
                                                                  code := mload(add(data, 36))
                                                              }
                                                              return string(abi.encodePacked(prefix, "Panic(", _toHex(code), ")"));
                                                          }
                                                  
                                                          return string(abi.encodePacked(prefix, "Unknown(", _toHex(data), ")"));
                                                      }
                                                  
                                                      function _toHex(uint256 value) private pure returns(string memory) {
                                                          return _toHex(abi.encodePacked(value));
                                                      }
                                                  
                                                      function _toHex(bytes memory data) private pure returns(string memory) {
                                                          bytes16 alphabet = 0x30313233343536373839616263646566;
                                                          bytes memory str = new bytes(2 + data.length * 2);
                                                          str[0] = "0";
                                                          str[1] = "x";
                                                          for (uint256 i = 0; i < data.length; i++) {
                                                              str[2 * i + 2] = alphabet[uint8(data[i] >> 4)];
                                                              str[2 * i + 3] = alphabet[uint8(data[i] & 0x0f)];
                                                          }
                                                          return string(str);
                                                      }
                                                  }
                                                  
                                                  
                                                  // File contracts/interfaces/IERC20Permit.sol
                                                  
                                                  
                                                  
                                                  pragma solidity ^0.6.12;
                                                  
                                                  
                                                  interface IERC20Permit {
                                                      function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
                                                  }
                                                  
                                                  
                                                  // File contracts/helpers/Permitable.sol
                                                  
                                                  
                                                  
                                                  pragma solidity ^0.6.12;
                                                  
                                                  
                                                  
                                                  contract Permitable {
                                                      event Error(
                                                          string reason
                                                      );
                                                  
                                                      function _permit(IERC20 token, uint256 amount, bytes calldata permit) internal {
                                                          if (permit.length == 32 * 7) {
                                                              // solhint-disable-next-line avoid-low-level-calls
                                                              (bool success, bytes memory result) = address(token).call(abi.encodePacked(IERC20Permit.permit.selector, permit));
                                                              if (!success) {
                                                                  string memory reason = RevertReasonParser.parse(result, "Permit call failed: ");
                                                                  if (token.allowance(msg.sender, address(this)) < amount) {
                                                                      revert(reason);
                                                                  } else {
                                                                      emit Error(reason);
                                                                  }
                                                              }
                                                          }
                                                      }
                                                  }
                                                  
                                                  
                                                  // File contracts/UnoswapRouter.sol
                                                  
                                                  
                                                  
                                                  pragma solidity ^0.6.12;
                                                  
                                                  contract UnoswapRouter is Permitable {
                                                      uint256 private constant _TRANSFER_FROM_CALL_SELECTOR_32 = 0x23b872dd00000000000000000000000000000000000000000000000000000000;
                                                      uint256 private constant _WETH_DEPOSIT_CALL_SELECTOR_32 = 0xd0e30db000000000000000000000000000000000000000000000000000000000;
                                                      uint256 private constant _WETH_WITHDRAW_CALL_SELECTOR_32 = 0x2e1a7d4d00000000000000000000000000000000000000000000000000000000;
                                                      uint256 private constant _ERC20_TRANSFER_CALL_SELECTOR_32 = 0xa9059cbb00000000000000000000000000000000000000000000000000000000;
                                                      uint256 private constant _ADDRESS_MASK =   0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
                                                      uint256 private constant _REVERSE_MASK =   0x8000000000000000000000000000000000000000000000000000000000000000;
                                                      uint256 private constant _WETH_MASK =      0x4000000000000000000000000000000000000000000000000000000000000000;
                                                      uint256 private constant _NUMERATOR_MASK = 0x0000000000000000ffffffff0000000000000000000000000000000000000000;
                                                      uint256 private constant _WETH = 0x000000000000000000000000C02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
                                                      uint256 private constant _UNISWAP_PAIR_RESERVES_CALL_SELECTOR_32 = 0x0902f1ac00000000000000000000000000000000000000000000000000000000;
                                                      uint256 private constant _UNISWAP_PAIR_SWAP_CALL_SELECTOR_32 = 0x022c0d9f00000000000000000000000000000000000000000000000000000000;
                                                      uint256 private constant _DENOMINATOR = 1000000000;
                                                      uint256 private constant _NUMERATOR_OFFSET = 160;
                                                  
                                                      receive() external payable {
                                                          // solhint-disable-next-line avoid-tx-origin
                                                          require(msg.sender != tx.origin, "ETH deposit rejected");
                                                      }
                                                  
                                                      function unoswapWithPermit(
                                                          IERC20 srcToken,
                                                          uint256 amount,
                                                          uint256 minReturn,
                                                          bytes32[] calldata pools,
                                                          bytes calldata permit
                                                      ) external payable returns(uint256 returnAmount) {
                                                          _permit(srcToken, amount, permit);
                                                          return unoswap(srcToken, amount, minReturn, pools);
                                                      }
                                                  
                                                      function unoswap(
                                                          IERC20 srcToken,
                                                          uint256 amount,
                                                          uint256 minReturn,
                                                          bytes32[] calldata /* pools */
                                                      ) public payable returns(uint256 returnAmount) {
                                                          assembly {  // solhint-disable-line no-inline-assembly
                                                              function reRevert() {
                                                                  returndatacopy(0, 0, returndatasize())
                                                                  revert(0, returndatasize())
                                                              }
                                                  
                                                              function revertWithReason(m, len) {
                                                                  mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                                                                  mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                                                                  mstore(0x40, m)
                                                                  revert(0, len)
                                                              }
                                                  
                                                              function swap(emptyPtr, swapAmount, pair, reversed, numerator, dst) -> ret {
                                                                  mstore(emptyPtr, _UNISWAP_PAIR_RESERVES_CALL_SELECTOR_32)
                                                                  if iszero(staticcall(gas(), pair, emptyPtr, 0x4, emptyPtr, 0x40)) {
                                                                      reRevert()
                                                                  }
                                                  
                                                                  let reserve0 := mload(emptyPtr)
                                                                  let reserve1 := mload(add(emptyPtr, 0x20))
                                                                  if reversed {
                                                                      let tmp := reserve0
                                                                      reserve0 := reserve1
                                                                      reserve1 := tmp
                                                                  }
                                                                  ret := mul(swapAmount, numerator)
                                                                  ret := div(mul(ret, reserve1), add(ret, mul(reserve0, _DENOMINATOR)))
                                                  
                                                                  mstore(emptyPtr, _UNISWAP_PAIR_SWAP_CALL_SELECTOR_32)
                                                                  switch reversed
                                                                  case 0 {
                                                                      mstore(add(emptyPtr, 0x04), 0)
                                                                      mstore(add(emptyPtr, 0x24), ret)
                                                                  }
                                                                  default {
                                                                      mstore(add(emptyPtr, 0x04), ret)
                                                                      mstore(add(emptyPtr, 0x24), 0)
                                                                  }
                                                                  mstore(add(emptyPtr, 0x44), dst)
                                                                  mstore(add(emptyPtr, 0x64), 0x80)
                                                                  mstore(add(emptyPtr, 0x84), 0)
                                                                  if iszero(call(gas(), pair, 0, emptyPtr, 0xa4, 0, 0)) {
                                                                      reRevert()
                                                                  }
                                                              }
                                                  
                                                              let emptyPtr := mload(0x40)
                                                              mstore(0x40, add(emptyPtr, 0xc0))
                                                  
                                                              let poolsOffset := add(calldataload(0x64), 0x4)
                                                              let poolsEndOffset := calldataload(poolsOffset)
                                                              poolsOffset := add(poolsOffset, 0x20)
                                                              poolsEndOffset := add(poolsOffset, mul(0x20, poolsEndOffset))
                                                              let rawPair := calldataload(poolsOffset)
                                                              switch srcToken
                                                              case 0 {
                                                                  if iszero(eq(amount, callvalue())) {
                                                                      revertWithReason(0x00000011696e76616c6964206d73672e76616c75650000000000000000000000, 0x55)  // "invalid msg.value"
                                                                  }
                                                  
                                                                  mstore(emptyPtr, _WETH_DEPOSIT_CALL_SELECTOR_32)
                                                                  if iszero(call(gas(), _WETH, amount, emptyPtr, 0x4, 0, 0)) {
                                                                      reRevert()
                                                                  }
                                                  
                                                                  mstore(emptyPtr, _ERC20_TRANSFER_CALL_SELECTOR_32)
                                                                  mstore(add(emptyPtr, 0x4), and(rawPair, _ADDRESS_MASK))
                                                                  mstore(add(emptyPtr, 0x24), amount)
                                                                  if iszero(call(gas(), _WETH, 0, emptyPtr, 0x44, 0, 0)) {
                                                                      reRevert()
                                                                  }
                                                              }
                                                              default {
                                                                  if callvalue() {
                                                                      revertWithReason(0x00000011696e76616c6964206d73672e76616c75650000000000000000000000, 0x55)  // "invalid msg.value"
                                                                  }
                                                  
                                                                  mstore(emptyPtr, _TRANSFER_FROM_CALL_SELECTOR_32)
                                                                  mstore(add(emptyPtr, 0x4), caller())
                                                                  mstore(add(emptyPtr, 0x24), and(rawPair, _ADDRESS_MASK))
                                                                  mstore(add(emptyPtr, 0x44), amount)
                                                                  if iszero(call(gas(), srcToken, 0, emptyPtr, 0x64, 0, 0)) {
                                                                      reRevert()
                                                                  }
                                                              }
                                                  
                                                              returnAmount := amount
                                                  
                                                              for {let i := add(poolsOffset, 0x20)} lt(i, poolsEndOffset) {i := add(i, 0x20)} {
                                                                  let nextRawPair := calldataload(i)
                                                  
                                                                  returnAmount := swap(
                                                                      emptyPtr,
                                                                      returnAmount,
                                                                      and(rawPair, _ADDRESS_MASK),
                                                                      and(rawPair, _REVERSE_MASK),
                                                                      shr(_NUMERATOR_OFFSET, and(rawPair, _NUMERATOR_MASK)),
                                                                      and(nextRawPair, _ADDRESS_MASK)
                                                                  )
                                                  
                                                                  rawPair := nextRawPair
                                                              }
                                                  
                                                              switch and(rawPair, _WETH_MASK)
                                                              case 0 {
                                                                  returnAmount := swap(
                                                                      emptyPtr,
                                                                      returnAmount,
                                                                      and(rawPair, _ADDRESS_MASK),
                                                                      and(rawPair, _REVERSE_MASK),
                                                                      shr(_NUMERATOR_OFFSET, and(rawPair, _NUMERATOR_MASK)),
                                                                      caller()
                                                                  )
                                                              }
                                                              default {
                                                                  returnAmount := swap(
                                                                      emptyPtr,
                                                                      returnAmount,
                                                                      and(rawPair, _ADDRESS_MASK),
                                                                      and(rawPair, _REVERSE_MASK),
                                                                      shr(_NUMERATOR_OFFSET, and(rawPair, _NUMERATOR_MASK)),
                                                                      address()
                                                                  )
                                                  
                                                                  mstore(emptyPtr, _WETH_WITHDRAW_CALL_SELECTOR_32)
                                                                  mstore(add(emptyPtr, 0x04), returnAmount)
                                                                  if iszero(call(gas(), _WETH, 0, emptyPtr, 0x24, 0, 0)) {
                                                                      reRevert()
                                                                  }
                                                  
                                                                  if iszero(call(gas(), caller(), returnAmount, 0, 0, 0, 0)) {
                                                                      reRevert()
                                                                  }
                                                              }
                                                  
                                                              if lt(returnAmount, minReturn) {
                                                                  revertWithReason(0x000000164d696e2072657475726e206e6f742072656163686564000000000000, 0x5a)  // "Min return not reached"
                                                              }
                                                          }
                                                      }
                                                  }
                                                  
                                                  
                                                  // File contracts/AggregationRouterV3.sol
                                                  
                                                  
                                                  
                                                  pragma solidity ^0.6.12;
                                                  pragma experimental ABIEncoderV2;
                                                  
                                                  
                                                  
                                                  
                                                  
                                                  
                                                  contract AggregationRouterV3 is Ownable, UnoswapRouter {
                                                      using SafeMath for uint256;
                                                      using SafeERC20 for IERC20;
                                                      using UniERC20 for IERC20;
                                                  
                                                      uint256 private constant _PARTIAL_FILL = 0x01;
                                                      uint256 private constant _REQUIRES_EXTRA_ETH = 0x02;
                                                      uint256 private constant _SHOULD_CLAIM = 0x04;
                                                      uint256 private constant _BURN_FROM_MSG_SENDER = 0x08;
                                                      uint256 private constant _BURN_FROM_TX_ORIGIN = 0x10;
                                                  
                                                      struct SwapDescription {
                                                          IERC20 srcToken;
                                                          IERC20 dstToken;
                                                          address srcReceiver;
                                                          address dstReceiver;
                                                          uint256 amount;
                                                          uint256 minReturnAmount;
                                                          uint256 flags;
                                                          bytes permit;
                                                      }
                                                  
                                                      event Swapped(
                                                          address sender,
                                                          IERC20 srcToken,
                                                          IERC20 dstToken,
                                                          address dstReceiver,
                                                          uint256 spentAmount,
                                                          uint256 returnAmount
                                                      );
                                                  
                                                      function discountedSwap(
                                                          IAggregationExecutor caller,
                                                          SwapDescription calldata desc,
                                                          bytes calldata data
                                                      )
                                                          external
                                                          payable
                                                          returns (uint256 returnAmount, uint256 gasLeft, uint256 chiSpent)
                                                      {
                                                          uint256 initialGas = gasleft();
                                                  
                                                          address chiSource = address(0);
                                                          if (desc.flags & _BURN_FROM_MSG_SENDER != 0) {
                                                              chiSource = msg.sender;
                                                          } else if (desc.flags & _BURN_FROM_TX_ORIGIN != 0) {
                                                              chiSource = tx.origin; // solhint-disable-line avoid-tx-origin
                                                          } else {
                                                              revert("Incorrect CHI burn flags");
                                                          }
                                                  
                                                          // solhint-disable-next-line avoid-low-level-calls
                                                          (bool success, bytes memory returnData) = address(this).delegatecall(abi.encodeWithSelector(this.swap.selector, caller, desc, data));
                                                          if (success) {
                                                              (returnAmount,) = abi.decode(returnData, (uint256, uint256));
                                                          } else {
                                                              if (msg.value > 0) {
                                                                  msg.sender.transfer(msg.value);
                                                              }
                                                              emit Error(RevertReasonParser.parse(returnData, "Swap failed: "));
                                                          }
                                                  
                                                          (IChi chi, uint256 amount) = caller.calculateGas(initialGas.sub(gasleft()), desc.flags, msg.data.length);
                                                          if (amount > 0) {
                                                              chiSpent = chi.freeFromUpTo(chiSource, amount);
                                                          }
                                                          gasLeft = gasleft();
                                                      }
                                                  
                                                      function swap(
                                                          IAggregationExecutor caller,
                                                          SwapDescription calldata desc,
                                                          bytes calldata data
                                                      )
                                                          external
                                                          payable
                                                          returns (uint256 returnAmount, uint256 gasLeft)
                                                      {
                                                          require(desc.minReturnAmount > 0, "Min return should not be 0");
                                                          require(data.length > 0, "data should be not zero");
                                                  
                                                          uint256 flags = desc.flags;
                                                          IERC20 srcToken = desc.srcToken;
                                                          IERC20 dstToken = desc.dstToken;
                                                  
                                                          if (flags & _REQUIRES_EXTRA_ETH != 0) {
                                                              require(msg.value > (srcToken.isETH() ? desc.amount : 0), "Invalid msg.value");
                                                          } else {
                                                              require(msg.value == (srcToken.isETH() ? desc.amount : 0), "Invalid msg.value");
                                                          }
                                                  
                                                          if (flags & _SHOULD_CLAIM != 0) {
                                                              require(!srcToken.isETH(), "Claim token is ETH");
                                                              _permit(srcToken, desc.amount, desc.permit);
                                                              srcToken.safeTransferFrom(msg.sender, desc.srcReceiver, desc.amount);
                                                          }
                                                  
                                                          address dstReceiver = (desc.dstReceiver == address(0)) ? msg.sender : desc.dstReceiver;
                                                          uint256 initialSrcBalance = (flags & _PARTIAL_FILL != 0) ? srcToken.uniBalanceOf(msg.sender) : 0;
                                                          uint256 initialDstBalance = dstToken.uniBalanceOf(dstReceiver);
                                                  
                                                          {
                                                              // solhint-disable-next-line avoid-low-level-calls
                                                              (bool success, bytes memory result) = address(caller).call{value: msg.value}(abi.encodePacked(caller.callBytes.selector, data));
                                                              if (!success) {
                                                                  revert(RevertReasonParser.parse(result, "callBytes failed: "));
                                                              }
                                                          }
                                                  
                                                          uint256 spentAmount = desc.amount;
                                                          returnAmount = dstToken.uniBalanceOf(dstReceiver).sub(initialDstBalance);
                                                  
                                                          if (flags & _PARTIAL_FILL != 0) {
                                                              spentAmount = initialSrcBalance.add(desc.amount).sub(srcToken.uniBalanceOf(msg.sender));
                                                              require(returnAmount.mul(desc.amount) >= desc.minReturnAmount.mul(spentAmount), "Return amount is not enough");
                                                          } else {
                                                              require(returnAmount >= desc.minReturnAmount, "Return amount is not enough");
                                                          }
                                                  
                                                          emit Swapped(
                                                              msg.sender,
                                                              srcToken,
                                                              dstToken,
                                                              dstReceiver,
                                                              spentAmount,
                                                              returnAmount
                                                          );
                                                  
                                                          gasLeft = gasleft();
                                                      }
                                                  
                                                      function rescueFunds(IERC20 token, uint256 amount) external onlyOwner {
                                                          token.uniTransfer(msg.sender, amount);
                                                      }
                                                  
                                                      function destroy() external onlyOwner {
                                                          selfdestruct(msg.sender);
                                                      }
                                                  }

                                                  File 2 of 6: MarsToken
                                                  pragma solidity ^0.5.0;
                                                  
                                                  /**
                                                   * @dev Wrappers over Solidity's arithmetic operations with added overflow
                                                   * checks.
                                                   *
                                                   * Arithmetic operations in Solidity wrap on overflow. This can easily result
                                                   * in bugs, because programmers usually assume that an overflow raises an
                                                   * error, which is the standard behavior in high level programming languages.
                                                   * `SafeMath` restores this intuition by reverting the transaction when an
                                                   * operation overflows.
                                                   *
                                                   * Using this library instead of the unchecked operations eliminates an entire
                                                   * class of bugs, so it's recommended to use it always.
                                                   */
                                                  library SafeMath {
                                                      /**
                                                       * @dev Returns the addition of two unsigned integers, reverting on
                                                       * overflow.
                                                       *
                                                       * Counterpart to Solidity's `+` operator.
                                                       *
                                                       * Requirements:
                                                       * - Addition cannot overflow.
                                                       */
                                                      function add(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          uint256 c = a + b;
                                                          require(c >= a, "SafeMath: addition overflow");
                                                  
                                                          return c;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the subtraction of two unsigned integers, reverting on
                                                       * overflow (when the result is negative).
                                                       *
                                                       * Counterpart to Solidity's `-` operator.
                                                       *
                                                       * Requirements:
                                                       * - Subtraction cannot overflow.
                                                       */
                                                      function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          return sub(a, b, "SafeMath: subtraction overflow");
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
                                                       * overflow (when the result is negative).
                                                       *
                                                       * Counterpart to Solidity's `-` operator.
                                                       *
                                                       * Requirements:
                                                       * - Subtraction cannot overflow.
                                                       *
                                                       * _Available since v2.4.0._
                                                       */
                                                      function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                                                          require(b <= a, errorMessage);
                                                          uint256 c = a - b;
                                                  
                                                          return c;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the multiplication of two unsigned integers, reverting on
                                                       * overflow.
                                                       *
                                                       * Counterpart to Solidity's `*` operator.
                                                       *
                                                       * Requirements:
                                                       * - Multiplication cannot overflow.
                                                       */
                                                      function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                                                          // benefit is lost if 'b' is also tested.
                                                          // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                                                          if (a == 0) {
                                                              return 0;
                                                          }
                                                  
                                                          uint256 c = a * b;
                                                          require(c / a == b, "SafeMath: multiplication overflow");
                                                  
                                                          return c;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the integer division of two unsigned integers. Reverts on
                                                       * division by zero. The result is rounded towards zero.
                                                       *
                                                       * Counterpart to Solidity's `/` operator. Note: this function uses a
                                                       * `revert` opcode (which leaves remaining gas untouched) while Solidity
                                                       * uses an invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       * - The divisor cannot be zero.
                                                       */
                                                      function div(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          return div(a, b, "SafeMath: division by zero");
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
                                                       * division by zero. The result is rounded towards zero.
                                                       *
                                                       * Counterpart to Solidity's `/` operator. Note: this function uses a
                                                       * `revert` opcode (which leaves remaining gas untouched) while Solidity
                                                       * uses an invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       * - The divisor cannot be zero.
                                                       *
                                                       * _Available since v2.4.0._
                                                       */
                                                      function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                                                          // Solidity only automatically asserts when dividing by 0
                                                          require(b > 0, errorMessage);
                                                          uint256 c = a / b;
                                                          // assert(a == b * c + a % b); // There is no case in which this doesn't hold
                                                  
                                                          return c;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
                                                       * Reverts when dividing by zero.
                                                       *
                                                       * Counterpart to Solidity's `%` operator. This function uses a `revert`
                                                       * opcode (which leaves remaining gas untouched) while Solidity uses an
                                                       * invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       * - The divisor cannot be zero.
                                                       */
                                                      function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          return mod(a, b, "SafeMath: modulo by zero");
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
                                                       * Reverts with custom message when dividing by zero.
                                                       *
                                                       * Counterpart to Solidity's `%` operator. This function uses a `revert`
                                                       * opcode (which leaves remaining gas untouched) while Solidity uses an
                                                       * invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       * - The divisor cannot be zero.
                                                       *
                                                       * _Available since v2.4.0._
                                                       */
                                                      function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                                                          require(b != 0, errorMessage);
                                                          return a % b;
                                                      }
                                                  }
                                                  
                                                  /*
                                                   * @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 GSN 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.
                                                   */
                                                  contract Context {
                                                      // Empty internal constructor, to prevent people from mistakenly deploying
                                                      // an instance of this contract, which should be used via inheritance.
                                                      constructor () internal { }
                                                      // solhint-disable-previous-line no-empty-blocks
                                                  
                                                      function _msgSender() internal view returns (address payable) {
                                                          return msg.sender;
                                                      }
                                                  
                                                      function _msgData() internal view returns (bytes memory) {
                                                          this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
                                                          return msg.data;
                                                      }
                                                  }
                                                  
                                                  /**
                                                   * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
                                                   * the optional functions; to access them see {ERC20Detailed}.
                                                   */
                                                  interface IERC20 {
                                                      /**
                                                       * @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 `recipient`.
                                                       *
                                                       * Returns a boolean value indicating whether the operation succeeded.
                                                       *
                                                       * Emits a {Transfer} event.
                                                       */
                                                      function transfer(address recipient, uint256 amount) external returns (bool);
                                                  
                                                      /**
                                                       * @dev Returns the remaining number of tokens that `spender` will be
                                                       * allowed to spend on behalf of `owner` through {transferFrom}. This is
                                                       * zero by default.
                                                       *
                                                       * This value changes when {approve} or {transferFrom} are called.
                                                       */
                                                      function allowance(address owner, address spender) external view returns (uint256);
                                                  
                                                      /**
                                                       * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
                                                       *
                                                       * Returns a boolean value indicating whether the operation succeeded.
                                                       *
                                                       * IMPORTANT: Beware that changing an allowance with this method brings the risk
                                                       * that someone may use both the old and the new allowance by unfortunate
                                                       * transaction ordering. One possible solution to mitigate this race
                                                       * condition is to first reduce the spender's allowance to 0 and set the
                                                       * desired value afterwards:
                                                       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                                                       *
                                                       * Emits an {Approval} event.
                                                       */
                                                      function approve(address spender, uint256 amount) external returns (bool);
                                                  
                                                      /**
                                                       * @dev Moves `amount` tokens from `sender` to `recipient` using the
                                                       * allowance mechanism. `amount` is then deducted from the caller's
                                                       * allowance.
                                                       *
                                                       * Returns a boolean value indicating whether the operation succeeded.
                                                       *
                                                       * Emits a {Transfer} event.
                                                       */
                                                      function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
                                                  
                                                      /**
                                                       * @dev Emitted when `value` tokens are moved from one account (`from`) to
                                                       * another (`to`).
                                                       *
                                                       * Note that `value` may be zero.
                                                       */
                                                      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);
                                                  }
                                                  
                                                  /**
                                                   * @dev Implementation of the {IERC20} interface.
                                                   *
                                                   * This implementation is agnostic to the way tokens are created. This means
                                                   * that a supply mechanism has to be added in a derived contract using {_mint}.
                                                   * For a generic mechanism see {ERC20Mintable}.
                                                   *
                                                   * TIP: For a detailed writeup see our guide
                                                   * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
                                                   * to implement supply mechanisms].
                                                   *
                                                   * We have followed general OpenZeppelin guidelines: functions revert instead
                                                   * of returning `false` on failure. This behavior is nonetheless conventional
                                                   * and does not conflict with the expectations of ERC20 applications.
                                                   *
                                                   * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
                                                   * This allows applications to reconstruct the allowance for all accounts just
                                                   * by listening to said events. Other implementations of the EIP may not emit
                                                   * these events, as it isn't required by the specification.
                                                   *
                                                   * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
                                                   * functions have been added to mitigate the well-known issues around setting
                                                   * allowances. See {IERC20-approve}.
                                                   */
                                                  contract ERC20 is Context, IERC20 {
                                                      using SafeMath for uint256;
                                                  
                                                      mapping (address => uint256) private _balances;
                                                  
                                                      mapping (address => mapping (address => uint256)) private _allowances;
                                                  
                                                      uint256 private _totalSupply;
                                                  
                                                      /**
                                                       * @dev See {IERC20-totalSupply}.
                                                       */
                                                      function totalSupply() public view returns (uint256) {
                                                          return _totalSupply;
                                                      }
                                                  
                                                      /**
                                                       * @dev See {IERC20-balanceOf}.
                                                       */
                                                      function balanceOf(address account) public view returns (uint256) {
                                                          return _balances[account];
                                                      }
                                                  
                                                      /**
                                                       * @dev See {IERC20-transfer}.
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - `recipient` cannot be the zero address.
                                                       * - the caller must have a balance of at least `amount`.
                                                       */
                                                      function transfer(address recipient, uint256 amount) public returns (bool) {
                                                          _transfer(_msgSender(), recipient, amount);
                                                          return true;
                                                      }
                                                  
                                                      /**
                                                       * @dev See {IERC20-allowance}.
                                                       */
                                                      function allowance(address owner, address spender) public view returns (uint256) {
                                                          return _allowances[owner][spender];
                                                      }
                                                  
                                                      /**
                                                       * @dev See {IERC20-approve}.
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - `spender` cannot be the zero address.
                                                       */
                                                      function approve(address spender, uint256 amount) public returns (bool) {
                                                          _approve(_msgSender(), spender, amount);
                                                          return true;
                                                      }
                                                  
                                                      /**
                                                       * @dev See {IERC20-transferFrom}.
                                                       *
                                                       * Emits an {Approval} event indicating the updated allowance. This is not
                                                       * required by the EIP. See the note at the beginning of {ERC20};
                                                       *
                                                       * Requirements:
                                                       * - `sender` and `recipient` cannot be the zero address.
                                                       * - `sender` must have a balance of at least `amount`.
                                                       * - the caller must have allowance for `sender`'s tokens of at least
                                                       * `amount`.
                                                       */
                                                      function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
                                                          _transfer(sender, recipient, amount);
                                                          _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
                                                          return true;
                                                      }
                                                  
                                                      /**
                                                       * @dev Atomically increases the allowance granted to `spender` by the caller.
                                                       *
                                                       * This is an alternative to {approve} that can be used as a mitigation for
                                                       * problems described in {IERC20-approve}.
                                                       *
                                                       * Emits an {Approval} event indicating the updated allowance.
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - `spender` cannot be the zero address.
                                                       */
                                                      function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
                                                          _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
                                                          return true;
                                                      }
                                                  
                                                      /**
                                                       * @dev Atomically decreases the allowance granted to `spender` by the caller.
                                                       *
                                                       * This is an alternative to {approve} that can be used as a mitigation for
                                                       * problems described in {IERC20-approve}.
                                                       *
                                                       * Emits an {Approval} event indicating the updated allowance.
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - `spender` cannot be the zero address.
                                                       * - `spender` must have allowance for the caller of at least
                                                       * `subtractedValue`.
                                                       */
                                                      function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
                                                          _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
                                                          return true;
                                                      }
                                                  
                                                      /**
                                                       * @dev Moves tokens `amount` from `sender` to `recipient`.
                                                       *
                                                       * This is internal function is equivalent to {transfer}, and can be used to
                                                       * e.g. implement automatic token fees, slashing mechanisms, etc.
                                                       *
                                                       * Emits a {Transfer} event.
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - `sender` cannot be the zero address.
                                                       * - `recipient` cannot be the zero address.
                                                       * - `sender` must have a balance of at least `amount`.
                                                       */
                                                      function _transfer(address sender, address recipient, uint256 amount) internal {
                                                          require(sender != address(0), "ERC20: transfer from the zero address");
                                                          require(recipient != address(0), "ERC20: transfer to the zero address");
                                                  
                                                          _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
                                                          _balances[recipient] = _balances[recipient].add(amount);
                                                          emit Transfer(sender, recipient, amount);
                                                      }
                                                  
                                                      /** @dev Creates `amount` tokens and assigns them to `account`, increasing
                                                       * the total supply.
                                                       *
                                                       * Emits a {Transfer} event with `from` set to the zero address.
                                                       *
                                                       * Requirements
                                                       *
                                                       * - `to` cannot be the zero address.
                                                       */
                                                      function _mint(address account, uint256 amount) internal {
                                                          require(account != address(0), "ERC20: mint to the zero address");
                                                  
                                                          _totalSupply = _totalSupply.add(amount);
                                                          _balances[account] = _balances[account].add(amount);
                                                          emit Transfer(address(0), account, amount);
                                                      }
                                                  
                                                      /**
                                                       * @dev Destroys `amount` tokens from `account`, reducing the
                                                       * total supply.
                                                       *
                                                       * Emits a {Transfer} event with `to` set to the zero address.
                                                       *
                                                       * Requirements
                                                       *
                                                       * - `account` cannot be the zero address.
                                                       * - `account` must have at least `amount` tokens.
                                                       */
                                                      function _burn(address account, uint256 amount) internal {
                                                          require(account != address(0), "ERC20: burn from the zero address");
                                                  
                                                          _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
                                                          _totalSupply = _totalSupply.sub(amount);
                                                          emit Transfer(account, address(0), amount);
                                                      }
                                                  
                                                      /**
                                                       * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
                                                       *
                                                       * This is internal function is equivalent to `approve`, and can be used to
                                                       * e.g. set automatic allowances for certain subsystems, etc.
                                                       *
                                                       * Emits an {Approval} event.
                                                       *
                                                       * Requirements:
                                                       *
                                                       * - `owner` cannot be the zero address.
                                                       * - `spender` cannot be the zero address.
                                                       */
                                                      function _approve(address owner, address spender, uint256 amount) internal {
                                                          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);
                                                      }
                                                  
                                                      /**
                                                       * @dev Destroys `amount` tokens from `account`.`amount` is then deducted
                                                       * from the caller's allowance.
                                                       *
                                                       * See {_burn} and {_approve}.
                                                       */
                                                      function _burnFrom(address account, uint256 amount) internal {
                                                          _burn(account, amount);
                                                          _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
                                                      }
                                                  }
                                                  
                                                  /**
                                                   * @dev Optional functions from the ERC20 standard.
                                                   */
                                                  contract ERC20Detailed is IERC20 {
                                                      string private _name;
                                                      string private _symbol;
                                                      uint8 private _decimals;
                                                  
                                                      /**
                                                       * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of
                                                       * these values are immutable: they can only be set once during
                                                       * construction.
                                                       */
                                                      constructor (string memory name, string memory symbol, uint8 decimals) public {
                                                          _name = name;
                                                          _symbol = symbol;
                                                          _decimals = decimals;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the name of the token.
                                                       */
                                                      function name() public view returns (string memory) {
                                                          return _name;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the symbol of the token, usually a shorter version of the
                                                       * name.
                                                       */
                                                      function symbol() public view returns (string memory) {
                                                          return _symbol;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the number of decimals used to get its user representation.
                                                       * For example, if `decimals` equals `2`, a balance of `505` tokens should
                                                       * be displayed to a user as `5,05` (`505 / 10 ** 2`).
                                                       *
                                                       * Tokens usually opt for a value of 18, imitating the relationship between
                                                       * Ether and Wei.
                                                       *
                                                       * NOTE: This information is only used for _display_ purposes: it in
                                                       * no way affects any of the arithmetic of the contract, including
                                                       * {IERC20-balanceOf} and {IERC20-transfer}.
                                                       */
                                                      function decimals() public view returns (uint8) {
                                                          return _decimals;
                                                      }
                                                  }
                                                  
                                                  /**
                                                   * @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.
                                                   *
                                                   * 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.
                                                   */
                                                  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 () internal {
                                                          address msgSender = _msgSender();
                                                          _owner = msgSender;
                                                          emit OwnershipTransferred(address(0), msgSender);
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the address of the current owner.
                                                       */
                                                      function owner() public view returns (address) {
                                                          return _owner;
                                                      }
                                                  
                                                      /**
                                                       * @dev Throws if called by any account other than the owner.
                                                       */
                                                      modifier onlyOwner() {
                                                          require(isOwner(), "Ownable: caller is not the owner");
                                                          _;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns true if the caller is the current owner.
                                                       */
                                                      function isOwner() public view returns (bool) {
                                                          return _msgSender() == _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 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 onlyOwner {
                                                          _transferOwnership(newOwner);
                                                      }
                                                  
                                                      /**
                                                       * @dev Transfers ownership of the contract to a new account (`newOwner`).
                                                       */
                                                      function _transferOwnership(address newOwner) internal {
                                                          require(newOwner != address(0), "Ownable: new owner is the zero address");
                                                          emit OwnershipTransferred(_owner, newOwner);
                                                          _owner = newOwner;
                                                      }
                                                  }
                                                  
                                                  contract MarsToken is ERC20, ERC20Detailed("MarsToken", "Mars", 18), Ownable {
                                                      function distributeMars(address _communityTreasury, address _teamTreasury, address _investorTreasury) external onlyOwner {
                                                          require(totalSupply() == 0, "token distributed");
                                                  
                                                          uint256 supply = 2_100_000_000e18; // 2.1 billion Mars
                                                          _mint(_communityTreasury, supply.mul(75).div(100));
                                                          _mint(_teamTreasury, supply.mul(20).div(100));
                                                          _mint(_investorTreasury, supply.mul(5).div(100));
                                                  
                                                          require(supply == totalSupply(), "total number of mars error");
                                                      }
                                                  
                                                      // Copied and modified from YAM code:
                                                      // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol
                                                      // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol
                                                      // Which is copied and modified from COMPOUND:
                                                      // https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol
                                                  
                                                      /// @notice A record of each accounts delegate
                                                      mapping (address => address) internal _delegates;
                                                  
                                                      /// @notice A checkpoint for marking number of votes from a given block
                                                      struct Checkpoint {
                                                          uint32 fromBlock;
                                                          uint256 votes;
                                                      }
                                                  
                                                      /// @notice A record of votes checkpoints for each account, by index
                                                      mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;
                                                  
                                                      /// @notice The number of checkpoints for each account
                                                      mapping (address => uint32) public numCheckpoints;
                                                  
                                                      /// @notice The EIP-712 typehash for the contract's domain
                                                      bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
                                                  
                                                      /// @notice The EIP-712 typehash for the delegation struct used by the contract
                                                      bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
                                                  
                                                      /// @notice A record of states for signing / validating signatures
                                                      mapping (address => uint) public nonces;
                                                  
                                                      /// @notice An event thats emitted when an account changes its delegate
                                                      event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
                                                  
                                                      /// @notice An event thats emitted when a delegate account's vote balance changes
                                                      event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
                                                  
                                                      /**
                                                       * @notice Delegate votes from `msg.sender` to `delegatee`
                                                       * @param delegator The address to get delegatee for
                                                       */
                                                      function delegates(address delegator)
                                                      external
                                                      view
                                                      returns (address)
                                                      {
                                                          return _delegates[delegator];
                                                      }
                                                  
                                                      /**
                                                       * @notice Delegate votes from `msg.sender` to `delegatee`
                                                       * @param delegatee The address to delegate votes to
                                                       */
                                                      function delegate(address delegatee) external {
                                                          return _delegate(msg.sender, delegatee);
                                                      }
                                                  
                                                      /**
                                                       * @notice Delegates votes from signatory to `delegatee`
                                                       * @param delegatee The address to delegate votes to
                                                       * @param nonce The contract state required to match the signature
                                                       * @param expiry The time at which to expire the signature
                                                       * @param v The recovery byte of the signature
                                                       * @param r Half of the ECDSA signature pair
                                                       * @param s Half of the ECDSA signature pair
                                                       */
                                                      function delegateBySig(
                                                          address delegatee,
                                                          uint nonce,
                                                          uint expiry,
                                                          uint8 v,
                                                          bytes32 r,
                                                          bytes32 s
                                                      )
                                                      external
                                                      {
                                                          bytes32 domainSeparator = keccak256(
                                                              abi.encode(
                                                                  DOMAIN_TYPEHASH,
                                                                  keccak256(bytes(name())),
                                                                  getChainId(),
                                                                  address(this)
                                                              )
                                                          );
                                                  
                                                          bytes32 structHash = keccak256(
                                                              abi.encode(
                                                                  DELEGATION_TYPEHASH,
                                                                  delegatee,
                                                                  nonce,
                                                                  expiry
                                                              )
                                                          );
                                                  
                                                          bytes32 digest = keccak256(
                                                              abi.encodePacked(
                                                                  "\x19\x01",
                                                                  domainSeparator,
                                                                  structHash
                                                              )
                                                          );
                                                  
                                                          address signatory = ecrecover(digest, v, r, s);
                                                          require(signatory != address(0), "MARS::delegateBySig: invalid signature");
                                                          require(nonce == nonces[signatory]++, "MARS::delegateBySig: invalid nonce");
                                                          require(now <= expiry, "MARS::delegateBySig: signature expired");
                                                          return _delegate(signatory, delegatee);
                                                      }
                                                  
                                                      /**
                                                       * @notice Gets the current votes balance for `account`
                                                       * @param account The address to get votes balance
                                                       * @return The number of current votes for `account`
                                                       */
                                                      function getCurrentVotes(address account)
                                                      external
                                                      view
                                                      returns (uint256)
                                                      {
                                                          uint32 nCheckpoints = numCheckpoints[account];
                                                          return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
                                                      }
                                                  
                                                      /**
                                                       * @notice Determine the prior number of votes for an account as of a block number
                                                       * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
                                                       * @param account The address of the account to check
                                                       * @param blockNumber The block number to get the vote balance at
                                                       * @return The number of votes the account had as of the given block
                                                       */
                                                      function getPriorVotes(address account, uint blockNumber)
                                                      external
                                                      view
                                                      returns (uint256)
                                                      {
                                                          require(blockNumber < block.number, "MARS::getPriorVotes: not yet determined");
                                                  
                                                          uint32 nCheckpoints = numCheckpoints[account];
                                                          if (nCheckpoints == 0) {
                                                              return 0;
                                                          }
                                                  
                                                          // First check most recent balance
                                                          if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
                                                              return checkpoints[account][nCheckpoints - 1].votes;
                                                          }
                                                  
                                                          // Next check implicit zero balance
                                                          if (checkpoints[account][0].fromBlock > blockNumber) {
                                                              return 0;
                                                          }
                                                  
                                                          uint32 lower = 0;
                                                          uint32 upper = nCheckpoints - 1;
                                                          while (upper > lower) {
                                                              uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
                                                              Checkpoint memory cp = checkpoints[account][center];
                                                              if (cp.fromBlock == blockNumber) {
                                                                  return cp.votes;
                                                              } else if (cp.fromBlock < blockNumber) {
                                                                  lower = center;
                                                              } else {
                                                                  upper = center - 1;
                                                              }
                                                          }
                                                          return checkpoints[account][lower].votes;
                                                      }
                                                  
                                                      function _delegate(address delegator, address delegatee)
                                                      internal
                                                      {
                                                          address currentDelegate = _delegates[delegator];
                                                          uint256 delegatorBalance = balanceOf(delegator); // balance of underlying MARSs (not scaled);
                                                          _delegates[delegator] = delegatee;
                                                  
                                                          emit DelegateChanged(delegator, currentDelegate, delegatee);
                                                  
                                                          _moveDelegates(currentDelegate, delegatee, delegatorBalance);
                                                      }
                                                  
                                                      function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
                                                          if (srcRep != dstRep && amount > 0) {
                                                              if (srcRep != address(0)) {
                                                                  // decrease old representative
                                                                  uint32 srcRepNum = numCheckpoints[srcRep];
                                                                  uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
                                                                  uint256 srcRepNew = srcRepOld.sub(amount);
                                                                  _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
                                                              }
                                                  
                                                              if (dstRep != address(0)) {
                                                                  // increase new representative
                                                                  uint32 dstRepNum = numCheckpoints[dstRep];
                                                                  uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
                                                                  uint256 dstRepNew = dstRepOld.add(amount);
                                                                  _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
                                                              }
                                                          }
                                                      }
                                                  
                                                      function _writeCheckpoint(
                                                          address delegatee,
                                                          uint32 nCheckpoints,
                                                          uint256 oldVotes,
                                                          uint256 newVotes
                                                      )
                                                      internal
                                                      {
                                                          uint32 blockNumber = safe32(block.number, "MARS::_writeCheckpoint: block number exceeds 32 bits");
                                                  
                                                          if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
                                                              checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
                                                          } else {
                                                              checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
                                                              numCheckpoints[delegatee] = nCheckpoints + 1;
                                                          }
                                                  
                                                          emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
                                                      }
                                                  
                                                      function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
                                                          require(n < 2**32, errorMessage);
                                                          return uint32(n);
                                                      }
                                                  
                                                      function getChainId() internal pure returns (uint) {
                                                          uint256 chainId;
                                                          assembly { chainId := chainid() }
                                                          return chainId;
                                                      }
                                                  }

                                                  File 3 of 6: UniswapV2Pair
                                                  // File: contracts/uniswapv2/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 migrator() 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;
                                                      function setMigrator(address) external;
                                                  }
                                                  
                                                  // File: contracts/uniswapv2/libraries/SafeMath.sol
                                                  
                                                  pragma solidity =0.6.12;
                                                  
                                                  // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
                                                  
                                                  library SafeMathUniswap {
                                                      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/uniswapv2/UniswapV2ERC20.sol
                                                  
                                                  pragma solidity =0.6.12;
                                                  
                                                  
                                                  contract UniswapV2ERC20 {
                                                      using SafeMathUniswap for uint;
                                                  
                                                      string public constant name = 'SushiSwap LP Token';
                                                      string public constant symbol = 'SLP';
                                                      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/uniswapv2/libraries/Math.sol
                                                  
                                                  pragma solidity =0.6.12;
                                                  
                                                  // 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/uniswapv2/libraries/UQ112x112.sol
                                                  
                                                  pragma solidity =0.6.12;
                                                  
                                                  // 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/uniswapv2/interfaces/IERC20.sol
                                                  
                                                  pragma solidity >=0.5.0;
                                                  
                                                  interface IERC20Uniswap {
                                                      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/uniswapv2/interfaces/IUniswapV2Callee.sol
                                                  
                                                  pragma solidity >=0.5.0;
                                                  
                                                  interface IUniswapV2Callee {
                                                      function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external;
                                                  }
                                                  
                                                  // File: contracts/uniswapv2/UniswapV2Pair.sol
                                                  
                                                  pragma solidity =0.6.12;
                                                  
                                                  
                                                  
                                                  
                                                  
                                                  
                                                  
                                                  
                                                  interface IMigrator {
                                                      // Return the desired amount of liquidity token that the migrator wants.
                                                      function desiredLiquidity() external view returns (uint256);
                                                  }
                                                  
                                                  contract UniswapV2Pair is UniswapV2ERC20 {
                                                      using SafeMathUniswap  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 = IERC20Uniswap(token0).balanceOf(address(this));
                                                          uint balance1 = IERC20Uniswap(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) {
                                                              address migrator = IUniswapV2Factory(factory).migrator();
                                                              if (msg.sender == migrator) {
                                                                  liquidity = IMigrator(migrator).desiredLiquidity();
                                                                  require(liquidity > 0 && liquidity != uint256(-1), "Bad desired liquidity");
                                                              } else {
                                                                  require(migrator == address(0), "Must not have migrator");
                                                                  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 = IERC20Uniswap(_token0).balanceOf(address(this));
                                                          uint balance1 = IERC20Uniswap(_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 = IERC20Uniswap(_token0).balanceOf(address(this));
                                                          balance1 = IERC20Uniswap(_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 = IERC20Uniswap(_token0).balanceOf(address(this));
                                                          balance1 = IERC20Uniswap(_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, IERC20Uniswap(_token0).balanceOf(address(this)).sub(reserve0));
                                                          _safeTransfer(_token1, to, IERC20Uniswap(_token1).balanceOf(address(this)).sub(reserve1));
                                                      }
                                                  
                                                      // force reserves to match balances
                                                      function sync() external lock {
                                                          _update(IERC20Uniswap(token0).balanceOf(address(this)), IERC20Uniswap(token1).balanceOf(address(this)), reserve0, reserve1);
                                                      }
                                                  }

                                                  File 4 of 6: TetherToken
                                                  pragma solidity ^0.4.17;
                                                  
                                                  /**
                                                   * @title SafeMath
                                                   * @dev Math operations with safety checks that throw on error
                                                   */
                                                  library SafeMath {
                                                      function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          if (a == 0) {
                                                              return 0;
                                                          }
                                                          uint256 c = a * b;
                                                          assert(c / a == b);
                                                          return c;
                                                      }
                                                  
                                                      function div(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          // assert(b > 0); // Solidity automatically throws when dividing by 0
                                                          uint256 c = a / b;
                                                          // assert(a == b * c + a % b); // There is no case in which this doesn't hold
                                                          return c;
                                                      }
                                                  
                                                      function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          assert(b <= a);
                                                          return a - b;
                                                      }
                                                  
                                                      function add(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          uint256 c = a + b;
                                                          assert(c >= a);
                                                          return c;
                                                      }
                                                  }
                                                  
                                                  /**
                                                   * @title Ownable
                                                   * @dev The Ownable contract has an owner address, and provides basic authorization control
                                                   * functions, this simplifies the implementation of "user permissions".
                                                   */
                                                  contract Ownable {
                                                      address public owner;
                                                  
                                                      /**
                                                        * @dev The Ownable constructor sets the original `owner` of the contract to the sender
                                                        * account.
                                                        */
                                                      function Ownable() public {
                                                          owner = msg.sender;
                                                      }
                                                  
                                                      /**
                                                        * @dev Throws if called by any account other than the owner.
                                                        */
                                                      modifier onlyOwner() {
                                                          require(msg.sender == owner);
                                                          _;
                                                      }
                                                  
                                                      /**
                                                      * @dev Allows the current owner to transfer control of the contract to a newOwner.
                                                      * @param newOwner The address to transfer ownership to.
                                                      */
                                                      function transferOwnership(address newOwner) public onlyOwner {
                                                          if (newOwner != address(0)) {
                                                              owner = newOwner;
                                                          }
                                                      }
                                                  
                                                  }
                                                  
                                                  /**
                                                   * @title ERC20Basic
                                                   * @dev Simpler version of ERC20 interface
                                                   * @dev see https://github.com/ethereum/EIPs/issues/20
                                                   */
                                                  contract ERC20Basic {
                                                      uint public _totalSupply;
                                                      function totalSupply() public constant returns (uint);
                                                      function balanceOf(address who) public constant returns (uint);
                                                      function transfer(address to, uint value) public;
                                                      event Transfer(address indexed from, address indexed to, uint value);
                                                  }
                                                  
                                                  /**
                                                   * @title ERC20 interface
                                                   * @dev see https://github.com/ethereum/EIPs/issues/20
                                                   */
                                                  contract ERC20 is ERC20Basic {
                                                      function allowance(address owner, address spender) public constant returns (uint);
                                                      function transferFrom(address from, address to, uint value) public;
                                                      function approve(address spender, uint value) public;
                                                      event Approval(address indexed owner, address indexed spender, uint value);
                                                  }
                                                  
                                                  /**
                                                   * @title Basic token
                                                   * @dev Basic version of StandardToken, with no allowances.
                                                   */
                                                  contract BasicToken is Ownable, ERC20Basic {
                                                      using SafeMath for uint;
                                                  
                                                      mapping(address => uint) public balances;
                                                  
                                                      // additional variables for use if transaction fees ever became necessary
                                                      uint public basisPointsRate = 0;
                                                      uint public maximumFee = 0;
                                                  
                                                      /**
                                                      * @dev Fix for the ERC20 short address attack.
                                                      */
                                                      modifier onlyPayloadSize(uint size) {
                                                          require(!(msg.data.length < size + 4));
                                                          _;
                                                      }
                                                  
                                                      /**
                                                      * @dev transfer token for a specified address
                                                      * @param _to The address to transfer to.
                                                      * @param _value The amount to be transferred.
                                                      */
                                                      function transfer(address _to, uint _value) public onlyPayloadSize(2 * 32) {
                                                          uint fee = (_value.mul(basisPointsRate)).div(10000);
                                                          if (fee > maximumFee) {
                                                              fee = maximumFee;
                                                          }
                                                          uint sendAmount = _value.sub(fee);
                                                          balances[msg.sender] = balances[msg.sender].sub(_value);
                                                          balances[_to] = balances[_to].add(sendAmount);
                                                          if (fee > 0) {
                                                              balances[owner] = balances[owner].add(fee);
                                                              Transfer(msg.sender, owner, fee);
                                                          }
                                                          Transfer(msg.sender, _to, sendAmount);
                                                      }
                                                  
                                                      /**
                                                      * @dev Gets the balance of the specified address.
                                                      * @param _owner The address to query the the balance of.
                                                      * @return An uint representing the amount owned by the passed address.
                                                      */
                                                      function balanceOf(address _owner) public constant returns (uint balance) {
                                                          return balances[_owner];
                                                      }
                                                  
                                                  }
                                                  
                                                  /**
                                                   * @title Standard ERC20 token
                                                   *
                                                   * @dev Implementation of the basic standard token.
                                                   * @dev https://github.com/ethereum/EIPs/issues/20
                                                   * @dev Based oncode by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
                                                   */
                                                  contract StandardToken is BasicToken, ERC20 {
                                                  
                                                      mapping (address => mapping (address => uint)) public allowed;
                                                  
                                                      uint public constant MAX_UINT = 2**256 - 1;
                                                  
                                                      /**
                                                      * @dev Transfer tokens from one address to another
                                                      * @param _from address The address which you want to send tokens from
                                                      * @param _to address The address which you want to transfer to
                                                      * @param _value uint the amount of tokens to be transferred
                                                      */
                                                      function transferFrom(address _from, address _to, uint _value) public onlyPayloadSize(3 * 32) {
                                                          var _allowance = allowed[_from][msg.sender];
                                                  
                                                          // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
                                                          // if (_value > _allowance) throw;
                                                  
                                                          uint fee = (_value.mul(basisPointsRate)).div(10000);
                                                          if (fee > maximumFee) {
                                                              fee = maximumFee;
                                                          }
                                                          if (_allowance < MAX_UINT) {
                                                              allowed[_from][msg.sender] = _allowance.sub(_value);
                                                          }
                                                          uint sendAmount = _value.sub(fee);
                                                          balances[_from] = balances[_from].sub(_value);
                                                          balances[_to] = balances[_to].add(sendAmount);
                                                          if (fee > 0) {
                                                              balances[owner] = balances[owner].add(fee);
                                                              Transfer(_from, owner, fee);
                                                          }
                                                          Transfer(_from, _to, sendAmount);
                                                      }
                                                  
                                                      /**
                                                      * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
                                                      * @param _spender The address which will spend the funds.
                                                      * @param _value The amount of tokens to be spent.
                                                      */
                                                      function approve(address _spender, uint _value) public onlyPayloadSize(2 * 32) {
                                                  
                                                          // To change the approve amount you first have to reduce the addresses`
                                                          //  allowance to zero by calling `approve(_spender, 0)` if it is not
                                                          //  already 0 to mitigate the race condition described here:
                                                          //  https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                                                          require(!((_value != 0) && (allowed[msg.sender][_spender] != 0)));
                                                  
                                                          allowed[msg.sender][_spender] = _value;
                                                          Approval(msg.sender, _spender, _value);
                                                      }
                                                  
                                                      /**
                                                      * @dev Function to check the amount of tokens than an owner allowed to a spender.
                                                      * @param _owner address The address which owns the funds.
                                                      * @param _spender address The address which will spend the funds.
                                                      * @return A uint specifying the amount of tokens still available for the spender.
                                                      */
                                                      function allowance(address _owner, address _spender) public constant returns (uint remaining) {
                                                          return allowed[_owner][_spender];
                                                      }
                                                  
                                                  }
                                                  
                                                  
                                                  /**
                                                   * @title Pausable
                                                   * @dev Base contract which allows children to implement an emergency stop mechanism.
                                                   */
                                                  contract Pausable is Ownable {
                                                    event Pause();
                                                    event Unpause();
                                                  
                                                    bool public paused = false;
                                                  
                                                  
                                                    /**
                                                     * @dev Modifier to make a function callable only when the contract is not paused.
                                                     */
                                                    modifier whenNotPaused() {
                                                      require(!paused);
                                                      _;
                                                    }
                                                  
                                                    /**
                                                     * @dev Modifier to make a function callable only when the contract is paused.
                                                     */
                                                    modifier whenPaused() {
                                                      require(paused);
                                                      _;
                                                    }
                                                  
                                                    /**
                                                     * @dev called by the owner to pause, triggers stopped state
                                                     */
                                                    function pause() onlyOwner whenNotPaused public {
                                                      paused = true;
                                                      Pause();
                                                    }
                                                  
                                                    /**
                                                     * @dev called by the owner to unpause, returns to normal state
                                                     */
                                                    function unpause() onlyOwner whenPaused public {
                                                      paused = false;
                                                      Unpause();
                                                    }
                                                  }
                                                  
                                                  contract BlackList is Ownable, BasicToken {
                                                  
                                                      /////// Getters to allow the same blacklist to be used also by other contracts (including upgraded Tether) ///////
                                                      function getBlackListStatus(address _maker) external constant returns (bool) {
                                                          return isBlackListed[_maker];
                                                      }
                                                  
                                                      function getOwner() external constant returns (address) {
                                                          return owner;
                                                      }
                                                  
                                                      mapping (address => bool) public isBlackListed;
                                                      
                                                      function addBlackList (address _evilUser) public onlyOwner {
                                                          isBlackListed[_evilUser] = true;
                                                          AddedBlackList(_evilUser);
                                                      }
                                                  
                                                      function removeBlackList (address _clearedUser) public onlyOwner {
                                                          isBlackListed[_clearedUser] = false;
                                                          RemovedBlackList(_clearedUser);
                                                      }
                                                  
                                                      function destroyBlackFunds (address _blackListedUser) public onlyOwner {
                                                          require(isBlackListed[_blackListedUser]);
                                                          uint dirtyFunds = balanceOf(_blackListedUser);
                                                          balances[_blackListedUser] = 0;
                                                          _totalSupply -= dirtyFunds;
                                                          DestroyedBlackFunds(_blackListedUser, dirtyFunds);
                                                      }
                                                  
                                                      event DestroyedBlackFunds(address _blackListedUser, uint _balance);
                                                  
                                                      event AddedBlackList(address _user);
                                                  
                                                      event RemovedBlackList(address _user);
                                                  
                                                  }
                                                  
                                                  contract UpgradedStandardToken is StandardToken{
                                                      // those methods are called by the legacy contract
                                                      // and they must ensure msg.sender to be the contract address
                                                      function transferByLegacy(address from, address to, uint value) public;
                                                      function transferFromByLegacy(address sender, address from, address spender, uint value) public;
                                                      function approveByLegacy(address from, address spender, uint value) public;
                                                  }
                                                  
                                                  contract TetherToken is Pausable, StandardToken, BlackList {
                                                  
                                                      string public name;
                                                      string public symbol;
                                                      uint public decimals;
                                                      address public upgradedAddress;
                                                      bool public deprecated;
                                                  
                                                      //  The contract can be initialized with a number of tokens
                                                      //  All the tokens are deposited to the owner address
                                                      //
                                                      // @param _balance Initial supply of the contract
                                                      // @param _name Token Name
                                                      // @param _symbol Token symbol
                                                      // @param _decimals Token decimals
                                                      function TetherToken(uint _initialSupply, string _name, string _symbol, uint _decimals) public {
                                                          _totalSupply = _initialSupply;
                                                          name = _name;
                                                          symbol = _symbol;
                                                          decimals = _decimals;
                                                          balances[owner] = _initialSupply;
                                                          deprecated = false;
                                                      }
                                                  
                                                      // Forward ERC20 methods to upgraded contract if this one is deprecated
                                                      function transfer(address _to, uint _value) public whenNotPaused {
                                                          require(!isBlackListed[msg.sender]);
                                                          if (deprecated) {
                                                              return UpgradedStandardToken(upgradedAddress).transferByLegacy(msg.sender, _to, _value);
                                                          } else {
                                                              return super.transfer(_to, _value);
                                                          }
                                                      }
                                                  
                                                      // Forward ERC20 methods to upgraded contract if this one is deprecated
                                                      function transferFrom(address _from, address _to, uint _value) public whenNotPaused {
                                                          require(!isBlackListed[_from]);
                                                          if (deprecated) {
                                                              return UpgradedStandardToken(upgradedAddress).transferFromByLegacy(msg.sender, _from, _to, _value);
                                                          } else {
                                                              return super.transferFrom(_from, _to, _value);
                                                          }
                                                      }
                                                  
                                                      // Forward ERC20 methods to upgraded contract if this one is deprecated
                                                      function balanceOf(address who) public constant returns (uint) {
                                                          if (deprecated) {
                                                              return UpgradedStandardToken(upgradedAddress).balanceOf(who);
                                                          } else {
                                                              return super.balanceOf(who);
                                                          }
                                                      }
                                                  
                                                      // Forward ERC20 methods to upgraded contract if this one is deprecated
                                                      function approve(address _spender, uint _value) public onlyPayloadSize(2 * 32) {
                                                          if (deprecated) {
                                                              return UpgradedStandardToken(upgradedAddress).approveByLegacy(msg.sender, _spender, _value);
                                                          } else {
                                                              return super.approve(_spender, _value);
                                                          }
                                                      }
                                                  
                                                      // Forward ERC20 methods to upgraded contract if this one is deprecated
                                                      function allowance(address _owner, address _spender) public constant returns (uint remaining) {
                                                          if (deprecated) {
                                                              return StandardToken(upgradedAddress).allowance(_owner, _spender);
                                                          } else {
                                                              return super.allowance(_owner, _spender);
                                                          }
                                                      }
                                                  
                                                      // deprecate current contract in favour of a new one
                                                      function deprecate(address _upgradedAddress) public onlyOwner {
                                                          deprecated = true;
                                                          upgradedAddress = _upgradedAddress;
                                                          Deprecate(_upgradedAddress);
                                                      }
                                                  
                                                      // deprecate current contract if favour of a new one
                                                      function totalSupply() public constant returns (uint) {
                                                          if (deprecated) {
                                                              return StandardToken(upgradedAddress).totalSupply();
                                                          } else {
                                                              return _totalSupply;
                                                          }
                                                      }
                                                  
                                                      // Issue a new amount of tokens
                                                      // these tokens are deposited into the owner address
                                                      //
                                                      // @param _amount Number of tokens to be issued
                                                      function issue(uint amount) public onlyOwner {
                                                          require(_totalSupply + amount > _totalSupply);
                                                          require(balances[owner] + amount > balances[owner]);
                                                  
                                                          balances[owner] += amount;
                                                          _totalSupply += amount;
                                                          Issue(amount);
                                                      }
                                                  
                                                      // Redeem tokens.
                                                      // These tokens are withdrawn from the owner address
                                                      // if the balance must be enough to cover the redeem
                                                      // or the call will fail.
                                                      // @param _amount Number of tokens to be issued
                                                      function redeem(uint amount) public onlyOwner {
                                                          require(_totalSupply >= amount);
                                                          require(balances[owner] >= amount);
                                                  
                                                          _totalSupply -= amount;
                                                          balances[owner] -= amount;
                                                          Redeem(amount);
                                                      }
                                                  
                                                      function setParams(uint newBasisPoints, uint newMaxFee) public onlyOwner {
                                                          // Ensure transparency by hardcoding limit beyond which fees can never be added
                                                          require(newBasisPoints < 20);
                                                          require(newMaxFee < 50);
                                                  
                                                          basisPointsRate = newBasisPoints;
                                                          maximumFee = newMaxFee.mul(10**decimals);
                                                  
                                                          Params(basisPointsRate, maximumFee);
                                                      }
                                                  
                                                      // Called when new token are issued
                                                      event Issue(uint amount);
                                                  
                                                      // Called when tokens are redeemed
                                                      event Redeem(uint amount);
                                                  
                                                      // Called when contract is deprecated
                                                      event Deprecate(address newAddress);
                                                  
                                                      // Called if contract ever adds fees
                                                      event Params(uint feeBasisPoints, uint maxFee);
                                                  }

                                                  File 5 of 6: 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 6 of 6: ChiToken
                                                  /*
                                                                                                                   ,╖╗#▒▓▓▓▓▓╣╬╣▓▓▓▓▒#╗╗╓,
                                                                                                             ,╗@▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓▓╗╖
                                                                                                         ╓#▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╝▀╠╠▄╣╝╜"""╙╙▀╝╝╣╬╬╬╬▓▌╖
                                                                                                      ╓▓╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▀`╓å▓▓▓╙  ,▄▓▓██▓▓▓▄▄▄▄▄╠╠╙╠▄▄
                                                                                                   ╓@╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▌  ê`'     *▀▀▀▀▀▀▀▓██████████████▄
                                                                                                 ╔▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬                      ╙▀████████████▌
                                                                                               ╓▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬                         ╙████████████▌
                                                                                             ,▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓▀                          ╗▄█████████████▄
                                                                                            é╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓▌   #╙                       ╙▀█████████████▓
                                                                                           ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▀              ╙▓╬╣▓▄            ╙▀▀███████████µ
                                                                                          ▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▀╣╝╙             ╒▓╬╬╬╬╬╬▓         ╙████████████████µ
                                                                                         ▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▌              ╖╖╖▄▓╬╬╬╬╬╬╬▓         █████████████████µ
                                                                                        ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬        ,#▓╣╬╬▓╬╬╬╬╬╬╬╬╬╬╬╬▌         ▓█████████████████
                                                                                       ]╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╓╖     ]╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╣╨          ██████████████████▌
                                                                                       ▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓▌╖,   ╙╠╠▓╬╬╬╬╬╬╬╬╬▓╝╙           ╫███████████████████
                                                                                      ]╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╝▀╙              ▓████████████████████▌
                                                                                      ║╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╝▀╙`                 ▄███████████████████████
                                                                                      ╟╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓╝▀╙                     ,▄█████████████████████████
                                                                                      ╟╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╝╜`                       ▄▓████████████████████████████
                                                                                      ║╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╣▀`                     ,▄▄▓████████████████████████████████
                                                                                      ▐╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓╙                       ,,,▄╠▓██████████████████████████████▌
                                                                                       ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬▓╙╔▒`               ╓▄▓████████████████████████████████████████⌐
                                                                                       ╚╬╬╬╬╬╬╬╬╬╬╬╬╬▓▓╣▓              ▄▓████████████████████████████████████████████
                                                                                        ▓╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬             ▄██████████████████████████████████████████████⌐
                                                                                         ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╛           ▄███████████████████████████████████████████████▌
                                                                                         └╣╬╬╬╬╬╬╬╬╬╬╬▓           ▄███████████████████████████████████████████████▌
                                                                                          └▓╬╬╬╬╬╬╬╬╬╬Γ          ]███████████████████████████████████████████████▀
                                                                                            ╣╬╬╬╬╬╬╬╬╬⌐          ╫████████████████████████████████▀▀▀▀▀▓████████╜
                                                                                             ╙╬╬╬╬╬╬╬╬⌐          ╟███████████████████████████▀╙    ,▄▓▓▓▓▓████▓
                                                                                               ╫╬╬╬╬╬╬b           ████████████████████████▀`    ,Φ▀▀█████████╙
                                                                                                 ╫╬╬╬╬▌╟           ██████████████████▀╓▀─       ▄▓█████████▀
                                                                                                   ╚╣╬▓╣▓           └▀████████████▀`         ╓▓█████████▓╙
                                                                                                     ╙╝╬╬▓             .▄▄▓█▀▀▀`           ▄▓█████████▀
                                                                                                        ╙▀▓▄                            ƒ,▓███████▀▀
                                                                                                            "                        ╓▓█▓█████▀▀└
                                                                                                                                 ╓▄▓████▀▀╙└
                                                  
                                                   ██████╗██╗  ██╗██╗     ██████╗  █████╗ ███████╗████████╗ ██████╗ ██╗  ██╗███████╗███╗   ██╗    ██████╗ ██╗   ██╗     ██╗██╗███╗   ██╗ ██████╗██╗  ██╗
                                                  ██╔════╝██║  ██║██║    ██╔════╝ ██╔══██╗██╔════╝╚══██╔══╝██╔═══██╗██║ ██╔╝██╔════╝████╗  ██║    ██╔══██╗╚██╗ ██╔╝    ███║██║████╗  ██║██╔════╝██║  ██║
                                                  ██║     ███████║██║    ██║  ███╗███████║███████╗   ██║   ██║   ██║█████╔╝ █████╗  ██╔██╗ ██║    ██████╔╝ ╚████╔╝     ╚██║██║██╔██╗ ██║██║     ███████║
                                                  ██║     ██╔══██║██║    ██║   ██║██╔══██║╚════██║   ██║   ██║   ██║██╔═██╗ ██╔══╝  ██║╚██╗██║    ██╔══██╗  ╚██╔╝       ██║██║██║╚██╗██║██║     ██╔══██║
                                                  ╚██████╗██║  ██║██║    ╚██████╔╝██║  ██║███████║   ██║   ╚██████╔╝██║  ██╗███████╗██║ ╚████║    ██████╔╝   ██║        ██║██║██║ ╚████║╚██████╗██║  ██║
                                                   ╚═════╝╚═╝  ╚═╝╚═╝     ╚═════╝ ╚═╝  ╚═╝╚══════╝   ╚═╝    ╚═════╝ ╚═╝  ╚═╝╚══════╝╚═╝  ╚═══╝    ╚═════╝    ╚═╝        ╚═╝╚═╝╚═╝  ╚═══╝ ╚═════╝╚═╝  ╚═╝
                                                  
                                                                                                               Copyright by 1inch Corporation
                                                                                                                   https://1inch.exchange
                                                  
                                                  ---
                                                  Deployer wallet address:
                                                  0x7E1E3334130355799F833ffec2D731BCa3E68aF6
                                                  
                                                  Signed raw transaction for chainId 1:
                                                  0xf90d7f808506fc23ac00830bd0fa8080b90d2c608060405234801561001057600080fd5b50610d0c806100206000396000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c806370a08231116100a2578063a9059cbb11610071578063a9059cbb14610305578063b0ac19a014610331578063d89135cd1461036a578063d8ccd0f314610372578063dd62ed3e1461038f5761010b565b806370a08231146102b057806395d89b41146102d6578063a0712d68146102de578063a2309ff8146102fd5761010b565b806323b872dd116100de57806323b872dd14610213578063313ce567146102495780635f2e2b45146102675780636366b936146102935761010b565b806306fdde0314610110578063079d229f1461018d578063095ea7b3146101cb57806318160ddd1461020b575b600080fd5b6101186103bd565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561015257818101518382015260200161013a565b50505050905090810190601f16801561017f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101b9600480360360408110156101a357600080fd5b506001600160a01b0381351690602001356103ee565b60408051918252519081900360200190f35b6101f7600480360360408110156101e157600080fd5b506001600160a01b03813516906020013561041f565b604080519115158252519081900360200190f35b6101b9610435565b6101f76004803603606081101561022957600080fd5b506001600160a01b03813581169160208101359091169060400135610453565b6102516104c2565b6040805160ff9092168252519081900360200190f35b6101b96004803603604081101561027d57600080fd5b506001600160a01b0381351690602001356104c7565b6101b9600480360360208110156102a957600080fd5b50356104e2565b6101b9600480360360208110156102c657600080fd5b50356001600160a01b03166104ff565b61011861051a565b6102fb600480360360208110156102f457600080fd5b5035610539565b005b6101b961070d565b6101f76004803603604081101561031b57600080fd5b506001600160a01b038135169060200135610713565b61034e6004803603602081101561034757600080fd5b5035610720565b604080516001600160a01b039092168252519081900360200190f35b6101b961078b565b6101b96004803603602081101561038857600080fd5b5035610791565b6101b9600480360360408110156103a557600080fd5b506001600160a01b03813581169160200135166107aa565b60405180604001604052806015815260200174086d0d2408ec2e6e8ded6cadc40c4f24062d2dcc6d605b1b81525081565b60006104188361041361040985610404886104ff565b6107d5565b61040487336107aa565b6104c7565b9392505050565b600061042c3384846107eb565b50600192915050565b600061044e60035460025461084d90919063ffffffff16565b905090565b600061046084848461088f565b6104b884336104b385604051806060016040528060288152602001610c8b602891396001600160a01b038a166000908152600160209081526040808320338452909152902054919063ffffffff61096116565b6107eb565b5060019392505050565b600081565b60006104d383836109f8565b6104dc82610a59565b50919050565b60006104f96104f483610404336104ff565b610791565b92915050565b6001600160a01b031660009081526020819052604090205490565b6040518060400160405280600381526020016243484960e81b81525081565b6002547f746d4946c0e9f43f4dee607b0ef1fa1c3318585733ff6000526015600bf30000600052602082045b80156106d85781601e600080f55060018201601e600080f55060028201601e600080f55060038201601e600080f55060048201601e600080f55060058201601e600080f55060068201601e600080f55060078201601e600080f55060088201601e600080f55060098201601e600080f550600a8201601e600080f550600b8201601e600080f550600c8201601e600080f550600d8201601e600080f550600e8201601e600080f550600f8201601e600080f55060108201601e600080f55060118201601e600080f55060128201601e600080f55060138201601e600080f55060148201601e600080f55060158201601e600080f55060168201601e600080f55060178201601e600080f55060188201601e600080f55060198201601e600080f550601a8201601e600080f550601b8201601e600080f550601c8201601e600080f550601d8201601e600080f550601e8201601e600080f550601f8201601e600080f5506020919091019060001901610565565b50601f82165b80156106fc5781601e600080f55060019190910190600019016106de565b506107073383610ad1565b60025550565b60025481565b600061042c33848461088f565b604080516001600160f81b03196020808301919091523060601b602183015260358201939093527f3c1644c68e5d6cb380c36d1bf847fdbc0c7ac28030025a2fc5e63cce23c16348605580830191909152825180830390910181526075909101909152805191012090565b60035481565b600061079d3383610b50565b6107a682610a59565b5090565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60008183106107e45781610418565b5090919050565b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600061041883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610961565b6108d281604051806060016040528060268152602001610c65602691396001600160a01b038616600090815260208190526040902054919063ffffffff61096116565b6001600160a01b038085166000908152602081905260408082209390935590841681522054610907908263ffffffff610be816565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156109f05760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156109b557818101518382015260200161099d565b50505050905090810190601f1680156109e25780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b610a028282610b50565b610a5582336104b384604051806060016040528060248152602001610cb3602491396001600160a01b0388166000908152600160209081526040808320338452909152902054919063ffffffff61096116565b5050565b60035460005b82811015610aca57610a72818301610720565b6040516001600160a01b039190911690600081818181865af19150503d8060008114610aba576040519150601f19603f3d011682016040523d82523d6000602084013e610abf565b606091505b505050600101610a5f565b5001600355565b6001600160a01b038216600090815260208190526040902054610afa908263ffffffff610be816565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b610b9381604051806060016040528060228152602001610c43602291396001600160a01b038516600090815260208190526040902054919063ffffffff61096116565b6001600160a01b038316600081815260208181526040808320949094558351858152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35050565b600082820183811015610418576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e20616d6f756e74206578636565647320616c6c6f77616e6365a2646970667358221220687f814fb4c0b3c6abd66ebdb1f1eabcf69becf92a382c3af453e0b21c3d15b564736f6c6343000608003325a00ed87a047b4e415bd7f8cf7a7ce5a1c204125df1cedc35c7bdcb71bd2a29a35ea02db2490337fa6c425f1b3d74b7b217de8b394adb3f571827629c06dc16364b66
                                                  ---
                                                  */
                                                  // File: @openzeppelin/contracts/math/Math.sol
                                                  
                                                  pragma solidity ^0.6.0;
                                                  
                                                  /**
                                                   * @dev Standard math utilities missing in the Solidity language.
                                                   */
                                                  library Math {
                                                      /**
                                                       * @dev Returns the largest of two numbers.
                                                       */
                                                      function max(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          return a >= b ? a : b;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the smallest of two numbers.
                                                       */
                                                      function min(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          return a < b ? a : b;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the average of two numbers. The result is rounded towards
                                                       * zero.
                                                       */
                                                      function average(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          // (a + b) / 2 can overflow, so we distribute
                                                          return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
                                                      }
                                                  }
                                                  
                                                  // File: @openzeppelin/contracts/math/SafeMath.sol
                                                  
                                                  pragma solidity ^0.6.0;
                                                  
                                                  /**
                                                   * @dev Wrappers over Solidity's arithmetic operations with added overflow
                                                   * checks.
                                                   *
                                                   * Arithmetic operations in Solidity wrap on overflow. This can easily result
                                                   * in bugs, because programmers usually assume that an overflow raises an
                                                   * error, which is the standard behavior in high level programming languages.
                                                   * `SafeMath` restores this intuition by reverting the transaction when an
                                                   * operation overflows.
                                                   *
                                                   * Using this library instead of the unchecked operations eliminates an entire
                                                   * class of bugs, so it's recommended to use it always.
                                                   */
                                                  library SafeMath {
                                                      /**
                                                       * @dev Returns the addition of two unsigned integers, reverting on
                                                       * overflow.
                                                       *
                                                       * Counterpart to Solidity's `+` operator.
                                                       *
                                                       * Requirements:
                                                       * - Addition cannot overflow.
                                                       */
                                                      function add(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          uint256 c = a + b;
                                                          require(c >= a, "SafeMath: addition overflow");
                                                  
                                                          return c;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the subtraction of two unsigned integers, reverting on
                                                       * overflow (when the result is negative).
                                                       *
                                                       * Counterpart to Solidity's `-` operator.
                                                       *
                                                       * Requirements:
                                                       * - Subtraction cannot overflow.
                                                       */
                                                      function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          return sub(a, b, "SafeMath: subtraction overflow");
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
                                                       * overflow (when the result is negative).
                                                       *
                                                       * Counterpart to Solidity's `-` operator.
                                                       *
                                                       * Requirements:
                                                       * - Subtraction cannot overflow.
                                                       */
                                                      function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                                                          require(b <= a, errorMessage);
                                                          uint256 c = a - b;
                                                  
                                                          return c;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the multiplication of two unsigned integers, reverting on
                                                       * overflow.
                                                       *
                                                       * Counterpart to Solidity's `*` operator.
                                                       *
                                                       * Requirements:
                                                       * - Multiplication cannot overflow.
                                                       */
                                                      function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
                                                          // benefit is lost if 'b' is also tested.
                                                          // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
                                                          if (a == 0) {
                                                              return 0;
                                                          }
                                                  
                                                          uint256 c = a * b;
                                                          require(c / a == b, "SafeMath: multiplication overflow");
                                                  
                                                          return c;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the integer division of two unsigned integers. Reverts on
                                                       * division by zero. The result is rounded towards zero.
                                                       *
                                                       * Counterpart to Solidity's `/` operator. Note: this function uses a
                                                       * `revert` opcode (which leaves remaining gas untouched) while Solidity
                                                       * uses an invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       * - The divisor cannot be zero.
                                                       */
                                                      function div(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          return div(a, b, "SafeMath: division by zero");
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
                                                       * division by zero. The result is rounded towards zero.
                                                       *
                                                       * Counterpart to Solidity's `/` operator. Note: this function uses a
                                                       * `revert` opcode (which leaves remaining gas untouched) while Solidity
                                                       * uses an invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       * - The divisor cannot be zero.
                                                       */
                                                      function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                                                          // Solidity only automatically asserts when dividing by 0
                                                          require(b > 0, errorMessage);
                                                          uint256 c = a / b;
                                                          // assert(a == b * c + a % b); // There is no case in which this doesn't hold
                                                  
                                                          return c;
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
                                                       * Reverts when dividing by zero.
                                                       *
                                                       * Counterpart to Solidity's `%` operator. This function uses a `revert`
                                                       * opcode (which leaves remaining gas untouched) while Solidity uses an
                                                       * invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       * - The divisor cannot be zero.
                                                       */
                                                      function mod(uint256 a, uint256 b) internal pure returns (uint256) {
                                                          return mod(a, b, "SafeMath: modulo by zero");
                                                      }
                                                  
                                                      /**
                                                       * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
                                                       * Reverts with custom message when dividing by zero.
                                                       *
                                                       * Counterpart to Solidity's `%` operator. This function uses a `revert`
                                                       * opcode (which leaves remaining gas untouched) while Solidity uses an
                                                       * invalid opcode to revert (consuming all remaining gas).
                                                       *
                                                       * Requirements:
                                                       * - The divisor cannot be zero.
                                                       */
                                                      function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
                                                          require(b != 0, errorMessage);
                                                          return a % b;
                                                      }
                                                  }
                                                  
                                                  // File: @openzeppelin/contracts/token/ERC20/IERC20.sol
                                                  
                                                  pragma solidity ^0.6.0;
                                                  
                                                  /**
                                                   * @dev Interface of the ERC20 standard as defined in the EIP.
                                                   */
                                                  interface IERC20 {
                                                      /**
                                                       * @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 `recipient`.
                                                       *
                                                       * Returns a boolean value indicating whether the operation succeeded.
                                                       *
                                                       * Emits a {Transfer} event.
                                                       */
                                                      function transfer(address recipient, uint256 amount) external returns (bool);
                                                  
                                                      /**
                                                       * @dev Returns the remaining number of tokens that `spender` will be
                                                       * allowed to spend on behalf of `owner` through {transferFrom}. This is
                                                       * zero by default.
                                                       *
                                                       * This value changes when {approve} or {transferFrom} are called.
                                                       */
                                                      function allowance(address owner, address spender) external view returns (uint256);
                                                  
                                                      /**
                                                       * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
                                                       *
                                                       * Returns a boolean value indicating whether the operation succeeded.
                                                       *
                                                       * IMPORTANT: Beware that changing an allowance with this method brings the risk
                                                       * that someone may use both the old and the new allowance by unfortunate
                                                       * transaction ordering. One possible solution to mitigate this race
                                                       * condition is to first reduce the spender's allowance to 0 and set the
                                                       * desired value afterwards:
                                                       * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                                                       *
                                                       * Emits an {Approval} event.
                                                       */
                                                      function approve(address spender, uint256 amount) external returns (bool);
                                                  
                                                      /**
                                                       * @dev Moves `amount` tokens from `sender` to `recipient` using the
                                                       * allowance mechanism. `amount` is then deducted from the caller's
                                                       * allowance.
                                                       *
                                                       * Returns a boolean value indicating whether the operation succeeded.
                                                       *
                                                       * Emits a {Transfer} event.
                                                       */
                                                      function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
                                                  
                                                      /**
                                                       * @dev Emitted when `value` tokens are moved from one account (`from`) to
                                                       * another (`to`).
                                                       *
                                                       * Note that `value` may be zero.
                                                       */
                                                      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);
                                                  }
                                                  
                                                  // File: contracts/ChiToken.sol
                                                  
                                                  pragma solidity ^0.6.0;
                                                  
                                                  
                                                  
                                                  
                                                  
                                                  abstract contract ERC20WithoutTotalSupply is IERC20 {
                                                      using SafeMath for uint256;
                                                  
                                                      mapping(address => uint256) private _balances;
                                                      mapping(address => mapping(address => uint256)) private _allowances;
                                                  
                                                      function balanceOf(address account) public view override returns (uint256) {
                                                          return _balances[account];
                                                      }
                                                  
                                                      function allowance(address owner, address spender) public view override returns (uint256) {
                                                          return _allowances[owner][spender];
                                                      }
                                                  
                                                      function transfer(address recipient, uint256 amount) public override returns (bool) {
                                                          _transfer(msg.sender, recipient, amount);
                                                          return true;
                                                      }
                                                  
                                                      function approve(address spender, uint256 amount) public override returns (bool) {
                                                          _approve(msg.sender, spender, amount);
                                                          return true;
                                                      }
                                                  
                                                      function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
                                                          _transfer(sender, recipient, amount);
                                                          _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance"));
                                                          return true;
                                                      }
                                                  
                                                      function _transfer(address sender, address recipient, uint256 amount) internal {
                                                          _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
                                                          _balances[recipient] = _balances[recipient].add(amount);
                                                          emit Transfer(sender, recipient, amount);
                                                      }
                                                  
                                                      function _approve(address owner, address spender, uint256 amount) internal {
                                                          _allowances[owner][spender] = amount;
                                                          emit Approval(owner, spender, amount);
                                                      }
                                                  
                                                      function _mint(address account, uint256 amount) internal {
                                                          _balances[account] = _balances[account].add(amount);
                                                          emit Transfer(address(0), account, amount);
                                                      }
                                                  
                                                      function _burn(address account, uint256 amount) internal {
                                                          _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
                                                          emit Transfer(account, address(0), amount);
                                                      }
                                                  
                                                      function _burnFrom(address account, uint256 amount) internal {
                                                          _burn(account, amount);
                                                          _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount, "ERC20: burn amount exceeds allowance"));
                                                      }
                                                  }
                                                  
                                                  
                                                  contract ChiToken is IERC20, ERC20WithoutTotalSupply {
                                                      string constant public name = "Chi Gastoken by 1inch";
                                                      string constant public symbol = "CHI";
                                                      uint8 constant public decimals = 0;
                                                  
                                                      uint256 public totalMinted;
                                                      uint256 public totalBurned;
                                                  
                                                      function totalSupply() public view override returns(uint256) {
                                                          return totalMinted.sub(totalBurned);
                                                      }
                                                  
                                                      function mint(uint256 value) public {
                                                          uint256 offset = totalMinted;
                                                          assembly {
                                                              mstore(0, 0x746d4946c0e9F43F4Dee607b0eF1fA1c3318585733ff6000526015600bf30000)
                                                  
                                                              for {let i := div(value, 32)} i {i := sub(i, 1)} {
                                                                  pop(create2(0, 0, 30, add(offset, 0))) pop(create2(0, 0, 30, add(offset, 1)))
                                                                  pop(create2(0, 0, 30, add(offset, 2))) pop(create2(0, 0, 30, add(offset, 3)))
                                                                  pop(create2(0, 0, 30, add(offset, 4))) pop(create2(0, 0, 30, add(offset, 5)))
                                                                  pop(create2(0, 0, 30, add(offset, 6))) pop(create2(0, 0, 30, add(offset, 7)))
                                                                  pop(create2(0, 0, 30, add(offset, 8))) pop(create2(0, 0, 30, add(offset, 9)))
                                                                  pop(create2(0, 0, 30, add(offset, 10))) pop(create2(0, 0, 30, add(offset, 11)))
                                                                  pop(create2(0, 0, 30, add(offset, 12))) pop(create2(0, 0, 30, add(offset, 13)))
                                                                  pop(create2(0, 0, 30, add(offset, 14))) pop(create2(0, 0, 30, add(offset, 15)))
                                                                  pop(create2(0, 0, 30, add(offset, 16))) pop(create2(0, 0, 30, add(offset, 17)))
                                                                  pop(create2(0, 0, 30, add(offset, 18))) pop(create2(0, 0, 30, add(offset, 19)))
                                                                  pop(create2(0, 0, 30, add(offset, 20))) pop(create2(0, 0, 30, add(offset, 21)))
                                                                  pop(create2(0, 0, 30, add(offset, 22))) pop(create2(0, 0, 30, add(offset, 23)))
                                                                  pop(create2(0, 0, 30, add(offset, 24))) pop(create2(0, 0, 30, add(offset, 25)))
                                                                  pop(create2(0, 0, 30, add(offset, 26))) pop(create2(0, 0, 30, add(offset, 27)))
                                                                  pop(create2(0, 0, 30, add(offset, 28))) pop(create2(0, 0, 30, add(offset, 29)))
                                                                  pop(create2(0, 0, 30, add(offset, 30))) pop(create2(0, 0, 30, add(offset, 31)))
                                                                  offset := add(offset, 32)
                                                              }
                                                  
                                                              for {let i := and(value, 0x1F)} i {i := sub(i, 1)} {
                                                                  pop(create2(0, 0, 30, offset))
                                                                  offset := add(offset, 1)
                                                              }
                                                          }
                                                  
                                                          _mint(msg.sender, value);
                                                          totalMinted = offset;
                                                      }
                                                  
                                                      function computeAddress2(uint256 salt) public view returns (address) {
                                                          bytes32 _data = keccak256(
                                                              abi.encodePacked(bytes1(0xff), address(this), salt, bytes32(0x3c1644c68e5d6cb380c36d1bf847fdbc0c7ac28030025a2fc5e63cce23c16348))
                                                          );
                                                          return address(uint256(_data));
                                                      }
                                                  
                                                      function _destroyChildren(uint256 value) internal {
                                                          uint256 _totalBurned = totalBurned;
                                                          for (uint256 i = 0; i < value; i++) {
                                                              computeAddress2(_totalBurned + i).call("");
                                                          }
                                                          totalBurned = _totalBurned + value;
                                                      }
                                                  
                                                      function free(uint256 value) public returns (uint256)  {
                                                          _burn(msg.sender, value);
                                                          _destroyChildren(value);
                                                          return value;
                                                      }
                                                  
                                                      function freeUpTo(uint256 value) public returns (uint256) {
                                                          return free(Math.min(value, balanceOf(msg.sender)));
                                                      }
                                                  
                                                      function freeFrom(address from, uint256 value) public returns (uint256) {
                                                          _burnFrom(from, value);
                                                          _destroyChildren(value);
                                                          return value;
                                                      }
                                                  
                                                      function freeFromUpTo(address from, uint256 value) public returns (uint256) {
                                                          return freeFrom(from, Math.min(Math.min(value, balanceOf(from)), allowance(from, msg.sender)));
                                                      }
                                                  }