ETH Price: $3,381.17 (-1.92%)
Gas: 4 Gwei

Token

MiladyStation (MS)
 

Overview

Max Total Supply

363 MS

Holders

166

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
pinkbubblegum.eth
Balance
1 MS
0x7cd4854339e35fa0243792685baebce73d6a23d1
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
MiladyStation

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-12-10
*/

/*⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣷⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠿⣿⣿⣿⣿⣿⣿⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣠⣤⣴⣶⣾⣿⣷⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠻⢿⣿⣿⣿⣿⣷⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠻⢿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣾⣿⣿⣿⣿⣿⡿⠿⠟⠛⠉⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠻⣿⣿⣿⣆⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⡿⠟⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣿⣧⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⣿⣇⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣶⣿⣿⣿⣿⣿⣿⣿⣶⣤⡀⠀⠙⠋⠀⠀⠀
⠀⠀⠀⠀⠀⣠⣾⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⣾⠟⢋⣥⣤⠀⣶⣶⣶⣦⣤⣌⣉⠛⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⣴⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠋⢁⣴⣿⣿⡿⠀⣿⣿⣿⣿⣿⣿⣿⣷⡄⠀⠀⠀⠀⠀
⠀⠀⠀⣼⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣤⣤⣶⣶⣾⣿⣿⣿⣿⣷⣶⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⠁⠀⠀⢹⣿⣿⣿⣿⣿⣿⢻⣿⡄⠀⠀⠀⠀
⠀⠀⠀⠛⠋⠀⠀⠀⠀⠀⠀⠀⢀⣤⣾⣿⠿⠛⣛⣉⣉⣀⣀⡀⠀⠀⠀⠀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⢸⣿⣿⡄⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⡿⢋⣩⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣶⣦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣦⣀⣀⣴⣿⣿⣿⣿⣿⡿⢸⣿⢿⣷⡀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣡⣄⠀⠋⠁⠀⠈⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⡟⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⡿⠀⠛⠃⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣧⡀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⠛⠃⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠈⠁⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⢿⣿⣿⣿⣷⣦⣤⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣶⣶⠀⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⣿⠇⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⢠⣿⣿⣿⠟⠉⠀⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⠀⠀⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⢸⣿⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣼⣿⡟⠁⣠⣦⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠉⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⡆⠀⠀⢻⣿⣿⣿⣿⣿⣿⣿⠏⠀⣸⡏⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⣿⡏⠀⠀⣿⣿⡀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⢹⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣇⠀⠀⠀⠙⢿⣿⣿⡿⠟⠁⠀⣸⡿⠁⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⢸⣿⠁⠀⠀⢸⣿⣇⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⢀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣦⡀⠀⠀⠀⠈⠉⠀⠀⠀⣼⡿⠁⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠈⠁⠀⠀⠀⠀⢿⣿⡄⠀⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⣼⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣷⣦⣄⣀⠀⠀⢀⡈⠙⠁⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢻⣿⣆⠀⠀⠀⠉⠛⠿⢿⣿⣿⠿⠛⠁⠀⠀⠀⣠⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠿⣿⣿⣷⣿⣯⣤⣶⠄⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣿⣷⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠙⠛⠋⠁⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⢿⣷⣤⣀⠀⠀⠀⠀⠀⠀⠀⠺⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⢻⣿⣶⣤⣤⣤⣶⣷⣤⠈⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⣿⣿⣿⣿⡿⠿⠛⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠶⢤⣄⣀⣀⣤⠶⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
::::    ::::  ::::::::::: :::            :::     :::::::::  :::   :::  ::::::::  :::::::::::     :::     ::::::::::: :::::::::::  ::::::::  ::::    ::: 
+:+:+: :+:+:+     :+:     :+:          :+: :+:   :+:    :+: :+:   :+: :+:    :+:     :+:       :+: :+:       :+:         :+:     :+:    :+: :+:+:   :+: 
+:+ +:+:+ +:+     +:+     +:+         +:+   +:+  +:+    +:+  +:+ +:+  +:+            +:+      +:+   +:+      +:+         +:+     +:+    +:+ :+:+:+  +:+ 
+#+  +:+  +#+     +#+     +#+        +#++:++#++: +#+    +:+   +#++:   +#++:++#++     +#+     +#++:++#++:     +#+         +#+     +#+    +:+ +#+ +:+ +#+ 
+#+       +#+     +#+     +#+        +#+     +#+ +#+    +#+    +#+           +#+     +#+     +#+     +#+     +#+         +#+     +#+    +#+ +#+  +#+#+# 
#+#       #+#     #+#     #+#        #+#     #+# #+#    #+#    #+#    #+#    #+#     #+#     #+#     #+#     #+#         #+#     #+#    #+# #+#   #+#+# 
###       ### ########### ########## ###     ### #########     ###     ########      ###     ###     ###     ###     ###########  ########  ###    #### ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
*/
// File: IOperatorFilterRegistry.sol


pragma solidity ^0.8.13;

interface IOperatorFilterRegistry {
    function isOperatorAllowed(address registrant, address operator) external view returns (bool);
    function register(address registrant) external;
    function registerAndSubscribe(address registrant, address subscription) external;
    function registerAndCopyEntries(address registrant, address registrantToCopy) external;
    function unregister(address addr) external;
    function updateOperator(address registrant, address operator, bool filtered) external;
    function updateOperators(address registrant, address[] calldata operators, bool filtered) external;
    function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;
    function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;
    function subscribe(address registrant, address registrantToSubscribe) external;
    function unsubscribe(address registrant, bool copyExistingEntries) external;
    function subscriptionOf(address addr) external returns (address registrant);
    function subscribers(address registrant) external returns (address[] memory);
    function subscriberAt(address registrant, uint256 index) external returns (address);
    function copyEntriesOf(address registrant, address registrantToCopy) external;
    function isOperatorFiltered(address registrant, address operator) external returns (bool);
    function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);
    function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);
    function filteredOperators(address addr) external returns (address[] memory);
    function filteredCodeHashes(address addr) external returns (bytes32[] memory);
    function filteredOperatorAt(address registrant, uint256 index) external returns (address);
    function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);
    function isRegistered(address addr) external returns (bool);
    function codeHashOf(address addr) external returns (bytes32);
}

// File: OperatorFilterer.sol


pragma solidity ^0.8.13;


/**
 * @title  OperatorFilterer
 * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another
 *         registrant's entries in the OperatorFilterRegistry.
 * @dev    This smart contract is meant to be inherited by token contracts so they can use the following:
 *         - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods.
 *         - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods.
 */
abstract contract OperatorFilterer {
    error OperatorNotAllowed(address operator);

    IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY =
        IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);

    constructor(address subscriptionOrRegistrantToCopy, bool subscribe) {
        // If an inheriting token contract is deployed to a network without the registry deployed, the modifier
        // will not revert, but the contract will need to be registered with the registry once it is deployed in
        // order for the modifier to filter addresses.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (subscribe) {
                OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);
            } else {
                if (subscriptionOrRegistrantToCopy != address(0)) {
                    OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy);
                } else {
                    OPERATOR_FILTER_REGISTRY.register(address(this));
                }
            }
        }
    }

    modifier onlyAllowedOperator(address from) virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            // Allow spending tokens from addresses with balance
            // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred
            // from an EOA.
            if (from == msg.sender) {
                _;
                return;
            }
            if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), msg.sender)) {
                revert OperatorNotAllowed(msg.sender);
            }
        }
        _;
    }

    modifier onlyAllowedOperatorApproval(address operator) virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) {
                revert OperatorNotAllowed(operator);
            }
        }
        _;
    }
}

// File: DefaultOperatorFilterer.sol


pragma solidity ^0.8.13;


/**
 * @title  DefaultOperatorFilterer
 * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription.
 */
abstract contract DefaultOperatorFilterer is OperatorFilterer {
    address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);

    constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {}
}

// File: @openzeppelin/contracts/utils/math/SafeMath.sol


// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
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) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            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) {
        unchecked {
            // 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) {
        unchecked {
            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) {
        unchecked {
            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) {
        return a + b;
    }

    /**
     * @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 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) {
        return a * b;
    }

    /**
     * @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.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        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) {
        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) {
        unchecked {
            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.
     *
     * 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) {
        unchecked {
            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) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

// File: @openzeppelin/contracts/utils/Counters.sol


// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

// File: @openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library MathUpgradeable {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @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.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

// File: @openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

pragma solidity ^0.8.0;


/**
 * @dev String operations.
 */
library StringsUpgradeable {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = MathUpgradeable.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, MathUpgradeable.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

// File: @openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @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
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 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");

        (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 functionCallWithValue(target, data, 0, "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");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, 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) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // 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
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

// File: @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol


// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;


/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     * @custom:oz-retyped-from bool
     */
    uint8 private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint8 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
     * constructor.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        bool isTopLevelCall = !_initializing;
        require(
            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized < type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }

    /**
     * @dev Internal function that returns the initialized version. Returns `_initialized`
     */
    function _getInitializedVersion() internal view returns (uint8) {
        return _initialized;
    }

    /**
     * @dev Internal function that returns the initialized version. Returns `_initializing`
     */
    function _isInitializing() internal view returns (bool) {
        return _initializing;
    }
}

// File: @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^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 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 ContextUpgradeable is Initializable {
    function __Context_init() internal onlyInitializing {
    }

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

// File: @openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721ReceiverUpgradeable {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: @openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165Upgradeable {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;



/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
    function __ERC165_init() internal onlyInitializing {
    }

    function __ERC165_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165Upgradeable).interfaceId;
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

// File: @openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol


// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721Upgradeable is IERC165Upgradeable {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

// File: @openzeppelin/contracts-upgradeable/token/ERC721/extensions/IERC721MetadataUpgradeable.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721MetadataUpgradeable is IERC721Upgradeable {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

// File: @openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol


// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;









/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721Upgradeable, IERC721MetadataUpgradeable {
    using AddressUpgradeable for address;
    using StringsUpgradeable for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing {
        __ERC721_init_unchained(name_, symbol_);
    }

    function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {
        return
            interfaceId == type(IERC721Upgradeable).interfaceId ||
            interfaceId == type(IERC721MetadataUpgradeable).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: address zero is not a valid owner");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _ownerOf(tokenId);
        require(owner != address(0), "ERC721: invalid token ID");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721Upgradeable.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not token owner or approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
        _safeTransfer(from, to, tokenId, data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _ownerOf(tokenId) != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        address owner = ERC721Upgradeable.ownerOf(tokenId);
        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId, 1);

        // Check that tokenId was not minted by `_beforeTokenTransfer` hook
        require(!_exists(tokenId), "ERC721: token already minted");

        unchecked {
            // Will not overflow unless all 2**256 token ids are minted to the same owner.
            // Given that tokens are minted one by one, it is impossible in practice that
            // this ever happens. Might change if we allow batch minting.
            // The ERC fails to describe this case.
            _balances[to] += 1;
        }

        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId, 1);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721Upgradeable.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId, 1);

        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
        owner = ERC721Upgradeable.ownerOf(tokenId);

        // Clear approvals
        delete _tokenApprovals[tokenId];

        unchecked {
            // Cannot overflow, as that would require more tokens to be burned/transferred
            // out than the owner initially received through minting and transferring in.
            _balances[owner] -= 1;
        }
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);

        _afterTokenTransfer(owner, address(0), tokenId, 1);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721Upgradeable.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId, 1);

        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
        require(ERC721Upgradeable.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");

        // Clear approvals from the previous owner
        delete _tokenApprovals[tokenId];

        unchecked {
            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
            // `from`'s balance is the number of token held, which is at least one before the current
            // transfer.
            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
            // all 2**256 token ids to be minted, which in practice is impossible.
            _balances[from] -= 1;
            _balances[to] += 1;
        }
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId, 1);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits an {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721Upgradeable.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721ReceiverUpgradeable(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
                return retval == IERC721ReceiverUpgradeable.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
     * - When `from` is zero, the tokens will be minted for `to`.
     * - When `to` is zero, ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256, /* firstTokenId */
        uint256 batchSize
    ) internal virtual {
        if (batchSize > 1) {
            if (from != address(0)) {
                _balances[from] -= batchSize;
            }
            if (to != address(0)) {
                _balances[to] += batchSize;
            }
        }
    }

    /**
     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
     * - When `from` is zero, the tokens were minted for `to`.
     * - When `to` is zero, ``from``'s tokens were burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual {}

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[44] private __gap;
}

// File: @openzeppelin/contracts/utils/math/Math.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @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.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
        }
    }
}

// File: @openzeppelin/contracts/utils/Strings.sol


// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)

pragma solidity ^0.8.0;


/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

// File: @openzeppelin/contracts/utils/Context.sol


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^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 meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^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() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @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 {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// File: @openzeppelin/contracts/utils/Address.sol


// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @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
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 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");

        (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");

        (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");

        (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");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal 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
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol


// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: @openzeppelin/contracts/utils/introspection/ERC165.sol


// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol


// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;


/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol


// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

// File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol


// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;


/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the token collection symbol.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

// File: @openzeppelin/contracts/token/ERC721/ERC721.sol


// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;








/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: address zero is not a valid owner");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _ownerOf(tokenId);
        require(owner != address(0), "ERC721: invalid token ID");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        _requireMinted(tokenId);

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty
     * by default, can be overridden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not token owner or approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        _requireMinted(tokenId);

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public virtual override {
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
        _safeTransfer(from, to, tokenId, data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
     */
    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _ownerOf(tokenId) != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(
        address to,
        uint256 tokenId,
        bytes memory data
    ) internal virtual {
        _mint(to, tokenId);
        require(
            _checkOnERC721Received(address(0), to, tokenId, data),
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId, 1);

        // Check that tokenId was not minted by `_beforeTokenTransfer` hook
        require(!_exists(tokenId), "ERC721: token already minted");

        unchecked {
            // Will not overflow unless all 2**256 token ids are minted to the same owner.
            // Given that tokens are minted one by one, it is impossible in practice that
            // this ever happens. Might change if we allow batch minting.
            // The ERC fails to describe this case.
            _balances[to] += 1;
        }

        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId, 1);
    }

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     * This is an internal function that does not check if the sender is authorized to operate on the token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        _beforeTokenTransfer(owner, address(0), tokenId, 1);

        // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
        owner = ERC721.ownerOf(tokenId);

        // Clear approvals
        delete _tokenApprovals[tokenId];

        unchecked {
            // Cannot overflow, as that would require more tokens to be burned/transferred
            // out than the owner initially received through minting and transferring in.
            _balances[owner] -= 1;
        }
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);

        _afterTokenTransfer(owner, address(0), tokenId, 1);
    }

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId, 1);

        // Check that tokenId was not transferred by `_beforeTokenTransfer` hook
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");

        // Clear approvals from the previous owner
        delete _tokenApprovals[tokenId];

        unchecked {
            // `_balances[from]` cannot overflow for the same reason as described in `_burn`:
            // `from`'s balance is the number of token held, which is at least one before the current
            // transfer.
            // `_balances[to]` could overflow in the conditions described in `_mint`. That would require
            // all 2**256 token ids to be minted, which in practice is impossible.
            _balances[from] -= 1;
            _balances[to] += 1;
        }
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId, 1);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits an {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits an {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    /**
     * @dev Reverts if the `tokenId` has not been minted yet.
     */
    function _requireMinted(uint256 tokenId) internal view virtual {
        require(_exists(tokenId), "ERC721: invalid token ID");
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) private returns (bool) {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    /// @solidity memory-safe-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
     * - When `from` is zero, the tokens will be minted for `to`.
     * - When `to` is zero, ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256, /* firstTokenId */
        uint256 batchSize
    ) internal virtual {
        if (batchSize > 1) {
            if (from != address(0)) {
                _balances[from] -= batchSize;
            }
            if (to != address(0)) {
                _balances[to] += batchSize;
            }
        }
    }

    /**
     * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
     * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
     * - When `from` is zero, the tokens were minted for `to`.
     * - When `to` is zero, ``from``'s tokens were burned.
     * - `from` and `to` are never both zero.
     * - `batchSize` is non-zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual {}
}

// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol


// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Burnable.sol)

pragma solidity ^0.8.0;



/**
 * @title ERC721 Burnable Token
 * @dev ERC721 Token that can be burned (destroyed).
 */
abstract contract ERC721Burnable is Context, ERC721 {
    /**
     * @dev Burns `tokenId`. See {ERC721-_burn}.
     *
     * Requirements:
     *
     * - The caller must own `tokenId` or be an approved operator.
     */
    function burn(uint256 tokenId) public virtual {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
        _burn(tokenId);
    }
}

// File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol


// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol)

pragma solidity ^0.8.0;



/**
 * @dev This implements an optional extension of {ERC721} defined in the EIP that adds
 * enumerability of all the token ids in the contract as well as all token ids owned by each
 * account.
 */
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {
    // Mapping from owner to list of owned token IDs
    mapping(address => mapping(uint256 => uint256)) private _ownedTokens;

    // Mapping from token ID to index of the owner tokens list
    mapping(uint256 => uint256) private _ownedTokensIndex;

    // Array with all token ids, used for enumeration
    uint256[] private _allTokens;

    // Mapping from token id to position in the allTokens array
    mapping(uint256 => uint256) private _allTokensIndex;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) {
        return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
        return _ownedTokens[owner][index];
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _allTokens.length;
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds");
        return _allTokens[index];
    }

    /**
     * @dev See {ERC721-_beforeTokenTransfer}.
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual override {
        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);

        if (batchSize > 1) {
            // Will only trigger during construction. Batch transferring (minting) is not available afterwards.
            revert("ERC721Enumerable: consecutive transfers not supported");
        }

        uint256 tokenId = firstTokenId;

        if (from == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (from != to) {
            _removeTokenFromOwnerEnumeration(from, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (to != from) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    }

    /**
     * @dev Private function to add a token to this extension's ownership-tracking data structures.
     * @param to address representing the new owner of the given token ID
     * @param tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        uint256 length = ERC721.balanceOf(to);
        _ownedTokens[to][length] = tokenId;
        _ownedTokensIndex[tokenId] = length;
    }

    /**
     * @dev Private function to add a token to this extension's token tracking data structures.
     * @param tokenId uint256 ID of the token to be added to the tokens list
     */
    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    /**
     * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
     * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
     * gas optimizations e.g. when performing a transfer operation (avoiding double writes).
     * This has O(1) time complexity, but alters the order of the _ownedTokens array.
     * @param from address representing the previous owner of the given token ID
     * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = ERC721.balanceOf(from) - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
        }

        // This also deletes the contents at the last position of the array
        delete _ownedTokensIndex[tokenId];
        delete _ownedTokens[from][lastTokenIndex];
    }

    /**
     * @dev Private function to remove a token from this extension's token tracking data structures.
     * This has O(1) time complexity, but alters the order of the _allTokens array.
     * @param tokenId uint256 ID of the token to be removed from the tokens list
     */
    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
        // then delete the last slot (swap and pop).

        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
        // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
        // an 'if' statement (like in _removeTokenFromOwnerEnumeration)
        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
        _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index

        // This also deletes the contents at the last position of the array
        delete _allTokensIndex[tokenId];
        _allTokens.pop();
    }
}

// File: miladystation/MiladyStation.sol


pragma solidity ^0.8.17;












contract MiladyStation is ERC721, ERC721Enumerable, ERC721Burnable, DefaultOperatorFilterer, Ownable {
    using SafeMath for uint256;

    string public MILADYSTATION_PROVENANCE = "";
    string public IPFSURI = "";
    uint public constant maxMiladyPurchase = 30;
    uint256 public constant MAX_MILADYSTATIONS = 1212;
    bool public saleIsActive = false;
    uint256 public standardMiladyCount = 0;

    address public miladyAddress = 0x5Af0D9827E0c53E4799BB226655A1de152A425a5;
    
    address public ghibladyAddress = 0x186E74aD45bF81fb3712e9657560f8f6361cbBef;
    address public pixeladyAddress = 0x8Fc0D90f2C45a5e7f94904075c952e0943CFCCfd;
    address public cigawretteAddress = 0xEEd41d06AE195CA8f5CaCACE4cd691EE75F0683f;

    IERC721Enumerable milady = IERC721Enumerable(miladyAddress);

    IERC721Enumerable ghiblady = IERC721Enumerable(ghibladyAddress);
    IERC721Enumerable pixelady = IERC721Enumerable(pixeladyAddress);
    IERC721Enumerable cig = IERC721Enumerable(cigawretteAddress);
    
    mapping(address => bool) public whitelistHunMint;
    mapping(address => bool) public whitelistOneMint;
    mapping(address => bool) public miladyMinted;

    using Counters for Counters.Counter;

    Counters.Counter private _tokenIdCounter;

    constructor() ERC721("MiladyStation", "MS") {}

    function safeMint(address to) public onlyOwner {
        uint256 tokenId = _tokenIdCounter.current();
        _tokenIdCounter.increment();
        _safeMint(to, tokenId);
    }

    // the following functions are overrides for creator fee opensea default operator stuff

    function setApprovalForAll(address operator, bool approved) public override (ERC721, IERC721) onlyAllowedOperatorApproval(operator) {
        super.setApprovalForAll(operator, approved);
    }

    function approve(address operator, uint256 tokenId) public override (ERC721, IERC721) onlyAllowedOperatorApproval(operator) {
        super.approve(operator, tokenId);
    }

    function transferFrom(address from, address to, uint256 tokenId) public override (ERC721, IERC721) onlyAllowedOperator(from) {
        super.transferFrom(from, to, tokenId);
    }

    function safeTransferFrom(address from, address to, uint256 tokenId) public override (ERC721, IERC721) onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId);
    }

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data)
        public
        override (ERC721, IERC721)
        onlyAllowedOperator(from)
    {
        super.safeTransferFrom(from, to, tokenId, data);
    }

    // The following functions are overrides required by Solidity.

    function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize)
        internal
        override(ERC721, ERC721Enumerable)
    {
        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
    }

    function _baseURI() internal view virtual override(ERC721) returns (string memory) {
        return IPFSURI;
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721Enumerable)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }

    //
    //MiladyStation Provenance Hash is made from
    //sha1 1212 pngs then sha1 12 groups of 101 then sha1 4 groups of 3 then sha1 2 groups of 2 then sha1 2
    //...
    //...
    // [
    // 'f4820210e044e9c9a3ce932cdc1fb91b9f6f825a',
    // '507760d2f329474caebe7918c5eacd1839e4325a',
    // '85ae5b450c85385157d7e9642179aa65d0eac33f',
    // 'a4cc444bac6f1ef3f334e2a648d7840e05803d0e'
    // ]
    // [
    // '4961e0a943ab9fdbf74c6a40ca33a75732bd1ff9',
    // 'ca9b9b7c6f64cab15ba570c89f383e38dc350c71'
    // ]
    // [ '5ea9682efda08e3be695e1c665434cf8568c95c6' ]
    //

    function setProvenanceHash(string memory provenanceHash) public onlyOwner {
        MILADYSTATION_PROVENANCE = provenanceHash;
    }
    
    function withdraw() public onlyOwner {
        uint balance = address(this).balance;
        payable(msg.sender).transfer(balance);
    }

    // Milady check

    function miladyHolderCheck(address holder) public view returns (uint256) {
        uint256 tokenNum = 0;
        try milady.balanceOf(holder) returns (uint256 miladyHolderIndex) {
            // First token owned by user
            tokenNum = miladyHolderIndex;
        } catch (bytes memory) {
            // No tokens owned by user
        }
        return tokenNum;
    }
    
    //Friend check

    function miladyFriendCheck(address holder) public view returns (uint256) {
        //fake token number
        uint256 tokenNum = 0;
        try ghiblady.balanceOf(holder) returns (uint256 miladyGhibIndex) {
            // First token owned by user
            tokenNum += miladyGhibIndex;
        } catch (bytes memory) {
            // No tokens owned by user
        }
        try pixelady.balanceOf(holder) returns (uint256 miladyPixIndex) {
            // First token owned by user
            tokenNum += miladyPixIndex;
        } catch (bytes memory) {
            // No tokens owned by user
        }
        try cig.balanceOf(holder) returns (uint256 miladyCigIndex) {
            // First token owned by user
            tokenNum += miladyCigIndex;
        } catch (bytes memory) {
            // No tokens owned by user
        }
        return tokenNum;
    }

    // creator mint batch

    function editWhitelistHun(address[] memory array) public onlyOwner {
        for(uint256 i = 0; i < array.length; i++) {
            address addressElement = array[i];
            whitelistHunMint[addressElement] = true;
        } 
    }

    // secret free mint

    function editWhitelistOne(address[] memory array) public onlyOwner {
        for(uint256 i = 0; i < array.length; i++) {
            address addressElement = array[i];
            whitelistOneMint[addressElement] = true;
        } 
    }

    function reserveMintMiladys() public {
        uint mintAmount;
        uint256 miladys = miladyHolderCheck(msg.sender);
        if (whitelistHunMint[msg.sender]){
            mintAmount = 30;
        } else if (whitelistOneMint[msg.sender]){
            whitelistOneMint[msg.sender] = false;
            mintAmount = 2;
        } else if (miladys > 0 && !miladyMinted[msg.sender]){
            miladyMinted[msg.sender] = true;
            mintAmount = 1;
        } else {
            require(false, "Nice try buster");
        }
        uint i;
        for (i = 0; i < mintAmount && totalSupply() < 1212; i++) {
            uint supply = totalSupply();
            _safeMint(msg.sender, supply);
        }
    }
    
    function flipSaleState() public onlyOwner {
        saleIsActive = !saleIsActive;
    }
    
    function setBaseURI(string memory baseURI) public onlyOwner {
        IPFSURI = baseURI;
    }

    function mintMiladys(uint256 numberOfTokens) public payable {
        require(saleIsActive, "Sale must be active to mint Miladys");
        require(numberOfTokens <= maxMiladyPurchase, "Can only mint up to 30 tokens at a time");
        require(standardMiladyCount.add(numberOfTokens) < MAX_MILADYSTATIONS, "Purchase would exceed max supply of Miladys");
        uint256 miladyPrice;
        uint256 senderMiladyBalance = miladyHolderCheck(msg.sender);
        uint256 senderFriendBalance = miladyFriendCheck(msg.sender);

        //Prices defined 12/3/22
        //Mint for Miladys
        if (senderMiladyBalance > 0){
            if (numberOfTokens == 30) {
                miladyPrice = 2000000000000000; // 0.002 ETH 
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            } else if (numberOfTokens >= 15) {
                miladyPrice = 3000000000000000; // 0.003 ETH 
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            } else if (numberOfTokens >= 5) {
                miladyPrice = 4000000000000000; // 0.004 ETH 
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            } else {
                miladyPrice = 5000000000000000; // 0.005 ETH should be 6 dollars
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            }
        //Mint for Friend of Milady
        //Ghiblady, Pixelady, Cigawrette Honorable Mentions: Miaura, Sonora, Milaidy
        } else if (senderMiladyBalance == 0 && senderFriendBalance > 0){
          if (numberOfTokens == 30) {
                miladyPrice = 6000000000000000; // 0.006 ETH
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            } else if (numberOfTokens >= 15) {
                miladyPrice = 7000000000000000; // 0.007 ETH
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            } else if (numberOfTokens >= 5) {
                miladyPrice = 8000000000000000; // 0.008 ETH
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            } else {
                miladyPrice = 9000000000000000; // 0.009 ETH should be 11 dollars
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            }

        //Mint for Normies ( ͡° ͜ʖ ͡°)
        //NO MILADYS???? NO PIXELADYS?????? NO GHIBLADYS??????????? NO CIGLADYS???????????????????
        } else if (senderMiladyBalance == 0 && senderFriendBalance == 0) {
          if (numberOfTokens == 30) {
                miladyPrice = 9000000000000000; /// 0.009 ETH
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            } else if (numberOfTokens >= 15) {
                miladyPrice = 10000000000000000; // 0.010 ETH
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            } else if (numberOfTokens >= 5) {
                miladyPrice = 11000000000000000; // 0.011 ETH
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            } else {
                miladyPrice = 12000000000000000; // 0.012 ETH should be 15 dollars
                require(miladyPrice.mul(numberOfTokens) <= msg.value, "Ether value sent is not correct");
            }
        }
        for(uint i = 0; i < numberOfTokens; i++) {
            if (standardMiladyCount < MAX_MILADYSTATIONS) {
                _safeMint(msg.sender, totalSupply());
                standardMiladyCount++;
            }
        }
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"IPFSURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_MILADYSTATIONS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MILADYSTATION_PROVENANCE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cigawretteAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"array","type":"address[]"}],"name":"editWhitelistHun","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"array","type":"address[]"}],"name":"editWhitelistOne","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flipSaleState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ghibladyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMiladyPurchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miladyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"}],"name":"miladyFriendCheck","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"}],"name":"miladyHolderCheck","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"miladyMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"mintMiladys","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pixeladyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserveMintMiladys","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"safeMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"saleIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"provenanceHash","type":"string"}],"name":"setProvenanceHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"standardMiladyCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistHunMint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistOneMint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405260405180602001604052806000815250600b908162000024919062000962565b5060405180602001604052806000815250600c908162000045919062000962565b506000600d60006101000a81548160ff0219169083151502179055506000600e55735af0d9827e0c53e4799bb226655a1de152a425a5600f60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555073186e74ad45bf81fb3712e9657560f8f6361cbbef601060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550738fc0d90f2c45a5e7f94904075c952e0943cfccfd601160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555073eed41d06ae195ca8f5cacace4cd691ee75f0683f601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16601360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16601460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16601560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16601660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200035357600080fd5b50733cc6cdda760b79bafa08df41ecfa224f810dceb660016040518060400160405280600d81526020017f4d696c61647953746174696f6e000000000000000000000000000000000000008152506040518060400160405280600281526020017f4d530000000000000000000000000000000000000000000000000000000000008152508160009081620003e8919062000962565b508060019081620003fa919062000962565b50505060006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115620005f2578015620004b8576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16637d3e3dbe30846040518363ffffffff1660e01b81526004016200047e92919062000a8e565b600060405180830381600087803b1580156200049957600080fd5b505af1158015620004ae573d6000803e3d6000fd5b50505050620005f1565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161462000572576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663a0af290330846040518363ffffffff1660e01b81526004016200053892919062000a8e565b600060405180830381600087803b1580156200055357600080fd5b505af115801562000568573d6000803e3d6000fd5b50505050620005f0565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff16634420e486306040518263ffffffff1660e01b8152600401620005bb919062000abb565b600060405180830381600087803b158015620005d657600080fd5b505af1158015620005eb573d6000803e3d6000fd5b505050505b5b5b505062000614620006086200061a60201b60201c565b6200062260201b60201c565b62000ad8565b600033905090565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200076a57607f821691505b60208210810362000780576200077f62000722565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620007ea7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620007ab565b620007f68683620007ab565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b6000620008436200083d62000837846200080e565b62000818565b6200080e565b9050919050565b6000819050919050565b6200085f8362000822565b620008776200086e826200084a565b848454620007b8565b825550505050565b600090565b6200088e6200087f565b6200089b81848462000854565b505050565b5b81811015620008c357620008b760008262000884565b600181019050620008a1565b5050565b601f8211156200091257620008dc8162000786565b620008e7846200079b565b81016020851015620008f7578190505b6200090f62000906856200079b565b830182620008a0565b50505b505050565b600082821c905092915050565b6000620009376000198460080262000917565b1980831691505092915050565b600062000952838362000924565b9150826002028217905092915050565b6200096d82620006e8565b67ffffffffffffffff811115620009895762000988620006f3565b5b62000995825462000751565b620009a2828285620008c7565b600060209050601f831160018114620009da5760008415620009c5578287015190505b620009d1858262000944565b86555062000a41565b601f198416620009ea8662000786565b60005b8281101562000a1457848901518255600182019150602085019450602081019050620009ed565b8683101562000a34578489015162000a30601f89168262000924565b8355505b6001600288020188555050505b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000a768262000a49565b9050919050565b62000a888162000a69565b82525050565b600060408201905062000aa5600083018562000a7d565b62000ab4602083018462000a7d565b9392505050565b600060208201905062000ad2600083018462000a7d565b92915050565b615b818062000ae86000396000f3fe6080604052600436106102725760003560e01c806355f804b31161014f578063abaf648f116100c1578063e01559ca1161007a578063e01559ca14610967578063e380231514610992578063e985e9c5146109bd578063eb8d2444146109fa578063f2fde38b14610a25578063fc48984e14610a4e57610272565b8063abaf648f14610868578063ac54f0e814610891578063b1e283de146108bc578063b6d8e86f146108d8578063b88d4fde14610901578063c87b56dd1461092a57610272565b8063715018a611610113578063715018a61461076a5780637d5fcf9c146107815780638b83df45146107be5780638da5cb5b146107e957806395d89b4114610814578063a22cb4651461083f57610272565b806355f804b3146106715780635854d9491461069a5780636352211e146106c5578063635df4ab1461070257806370a082311461072d57610272565b80633494f1bf116101e857806341f43434116101ac57806341f434341461054f57806342842e0e1461057a57806342966c68146105a35780634b01570a146105cc5780634f6ccce71461060957806355e4ef9a1461064657610272565b80633494f1bf1461046a5780633c79f889146104a75780633ccfd60b146104d25780633eab9435146104e957806340d097c31461052657610272565b8063109695231161023a578063109695231461038257806318160ddd146103ab57806323b872dd146103d65780632f745c59146103ff578063323ab4741461043c57806334918dfd1461045357610272565b806301ffc9a71461027757806306fdde03146102b4578063081812fc146102df5780630920a7851461031c578063095ea7b314610359575b600080fd5b34801561028357600080fd5b5061029e60048036038101906102999190614226565b610a79565b6040516102ab919061426e565b60405180910390f35b3480156102c057600080fd5b506102c9610a8b565b6040516102d69190614319565b60405180910390f35b3480156102eb57600080fd5b5061030660048036038101906103019190614371565b610b1d565b60405161031391906143df565b60405180910390f35b34801561032857600080fd5b50610343600480360381019061033e9190614426565b610b63565b604051610350919061426e565b60405180910390f35b34801561036557600080fd5b50610380600480360381019061037b9190614453565b610b83565b005b34801561038e57600080fd5b506103a960048036038101906103a491906145c8565b610c8d565b005b3480156103b757600080fd5b506103c0610ca8565b6040516103cd9190614620565b60405180910390f35b3480156103e257600080fd5b506103fd60048036038101906103f8919061463b565b610cb5565b005b34801561040b57600080fd5b5061042660048036038101906104219190614453565b610e05565b6040516104339190614620565b60405180910390f35b34801561044857600080fd5b50610451610eaa565b005b34801561045f57600080fd5b50610468611118565b005b34801561047657600080fd5b50610491600480360381019061048c9190614426565b61114c565b60405161049e9190614620565b60405180910390f35b3480156104b357600080fd5b506104bc611232565b6040516104c991906143df565b60405180910390f35b3480156104de57600080fd5b506104e7611258565b005b3480156104f557600080fd5b50610510600480360381019061050b9190614426565b6112af565b60405161051d919061426e565b60405180910390f35b34801561053257600080fd5b5061054d60048036038101906105489190614426565b6112cf565b005b34801561055b57600080fd5b506105646112fd565b60405161057191906146ed565b60405180910390f35b34801561058657600080fd5b506105a1600480360381019061059c919061463b565b61130f565b005b3480156105af57600080fd5b506105ca60048036038101906105c59190614371565b61145f565b005b3480156105d857600080fd5b506105f360048036038101906105ee9190614426565b6114bb565b6040516106009190614620565b60405180910390f35b34801561061557600080fd5b50610630600480360381019061062b9190614371565b61176e565b60405161063d9190614620565b60405180910390f35b34801561065257600080fd5b5061065b6117df565b60405161066891906143df565b60405180910390f35b34801561067d57600080fd5b50610698600480360381019061069391906145c8565b611805565b005b3480156106a657600080fd5b506106af611820565b6040516106bc9190614319565b60405180910390f35b3480156106d157600080fd5b506106ec60048036038101906106e79190614371565b6118ae565b6040516106f991906143df565b60405180910390f35b34801561070e57600080fd5b50610717611934565b6040516107249190614620565b60405180910390f35b34801561073957600080fd5b50610754600480360381019061074f9190614426565b61193a565b6040516107619190614620565b60405180910390f35b34801561077657600080fd5b5061077f6119f1565b005b34801561078d57600080fd5b506107a860048036038101906107a39190614426565b611a05565b6040516107b5919061426e565b60405180910390f35b3480156107ca57600080fd5b506107d3611a25565b6040516107e09190614319565b60405180910390f35b3480156107f557600080fd5b506107fe611ab3565b60405161080b91906143df565b60405180910390f35b34801561082057600080fd5b50610829611add565b6040516108369190614319565b60405180910390f35b34801561084b57600080fd5b5061086660048036038101906108619190614734565b611b6f565b005b34801561087457600080fd5b5061088f600480360381019061088a919061483c565b611c79565b005b34801561089d57600080fd5b506108a6611d1c565b6040516108b391906143df565b60405180910390f35b6108d660048036038101906108d19190614371565b611d42565b005b3480156108e457600080fd5b506108ff60048036038101906108fa919061483c565b6123d5565b005b34801561090d57600080fd5b5061092860048036038101906109239190614926565b612478565b005b34801561093657600080fd5b50610951600480360381019061094c9190614371565b6125cb565b60405161095e9190614319565b60405180910390f35b34801561097357600080fd5b5061097c612633565b6040516109899190614620565b60405180910390f35b34801561099e57600080fd5b506109a7612638565b6040516109b49190614620565b60405180910390f35b3480156109c957600080fd5b506109e460048036038101906109df91906149a9565b61263e565b6040516109f1919061426e565b60405180910390f35b348015610a0657600080fd5b50610a0f6126d2565b604051610a1c919061426e565b60405180910390f35b348015610a3157600080fd5b50610a4c6004803603810190610a479190614426565b6126e5565b005b348015610a5a57600080fd5b50610a63612768565b604051610a7091906143df565b60405180910390f35b6000610a848261278e565b9050919050565b606060008054610a9a90614a18565b80601f0160208091040260200160405190810160405280929190818152602001828054610ac690614a18565b8015610b135780601f10610ae857610100808354040283529160200191610b13565b820191906000526020600020905b815481529060010190602001808311610af657829003601f168201915b5050505050905090565b6000610b2882612808565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60176020528060005260406000206000915054906101000a900460ff1681565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115610c7e576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401610bfb929190614a49565b602060405180830381865afa158015610c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3c9190614a87565b610c7d57806040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401610c7491906143df565b60405180910390fd5b5b610c888383612853565b505050565b610c9561296a565b80600b9081610ca49190614c56565b5050565b6000600880549050905090565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115610df3573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d2757610d228484846129e8565b610dff565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401610d70929190614a49565b602060405180830381865afa158015610d8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db19190614a87565b610df257336040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401610de991906143df565b60405180910390fd5b5b610dfe8484846129e8565b5b50505050565b6000610e108361193a565b8210610e51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e4890614d9a565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b600080610eb63361114c565b9050601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610f1357601e91506110ca565b601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610fc6576000601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600291506110c9565b6000811180156110205750601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16155b15611086576001601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600191506110c8565b60006110c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110be90614e06565b60405180910390fd5b5b5b5b60005b82811080156110e457506104bc6110e2610ca8565b105b156111135760006110f3610ca8565b90506110ff3382612a48565b50808061110b90614e55565b9150506110cd565b505050565b61112061296a565b600d60009054906101000a900460ff1615600d60006101000a81548160ff021916908315150217905550565b60008060009050601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231846040518263ffffffff1660e01b81526004016111ae91906143df565b602060405180830381865afa9250505080156111e857506040513d601f19601f820116820180604052508101906111e59190614eb2565b60015b611224573d8060008114611218576040519150601f19603f3d011682016040523d82523d6000602084013e61121d565b606091505b5050611229565b809150505b80915050919050565b601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61126061296a565b60004790503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156112ab573d6000803e3d6000fd5b5050565b60196020528060005260406000206000915054906101000a900460ff1681565b6112d761296a565b60006112e3601a612a66565b90506112ef601a612a74565b6112f98282612a48565b5050565b6daaeb6d7670e522a718067333cd4e81565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561144d573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036113815761137c848484612a8a565b611459565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b81526004016113ca929190614a49565b602060405180830381865afa1580156113e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140b9190614a87565b61144c57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161144391906143df565b60405180910390fd5b5b611458848484612a8a565b5b50505050565b61147061146a612aaa565b82612ab2565b6114af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114a690614f51565b60405180910390fd5b6114b881612b47565b50565b60008060009050601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231846040518263ffffffff1660e01b815260040161151d91906143df565b602060405180830381865afa92505050801561155757506040513d601f19601f820116820180604052508101906115549190614eb2565b60015b611593573d8060008114611587576040519150601f19603f3d011682016040523d82523d6000602084013e61158c565b606091505b50506115a3565b808261159f9190614f71565b9150505b601560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231846040518263ffffffff1660e01b81526004016115fe91906143df565b602060405180830381865afa92505050801561163857506040513d601f19601f820116820180604052508101906116359190614eb2565b60015b611674573d8060008114611668576040519150601f19603f3d011682016040523d82523d6000602084013e61166d565b606091505b5050611684565b80826116809190614f71565b9150505b601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231846040518263ffffffff1660e01b81526004016116df91906143df565b602060405180830381865afa92505050801561171957506040513d601f19601f820116820180604052508101906117169190614eb2565b60015b611755573d8060008114611749576040519150601f19603f3d011682016040523d82523d6000602084013e61174e565b606091505b5050611765565b80826117619190614f71565b9150505b80915050919050565b6000611778610ca8565b82106117b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b090615017565b60405180910390fd5b600882815481106117cd576117cc615037565b5b90600052602060002001549050919050565b601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61180d61296a565b80600c908161181c9190614c56565b5050565b600b805461182d90614a18565b80601f016020809104026020016040519081016040528092919081815260200182805461185990614a18565b80156118a65780601f1061187b576101008083540402835291602001916118a6565b820191906000526020600020905b81548152906001019060200180831161188957829003601f168201915b505050505081565b6000806118ba83612c95565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361192b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611922906150b2565b60405180910390fd5b80915050919050565b6104bc81565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036119aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119a190615144565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6119f961296a565b611a036000612cd2565b565b60186020528060005260406000206000915054906101000a900460ff1681565b600c8054611a3290614a18565b80601f0160208091040260200160405190810160405280929190818152602001828054611a5e90614a18565b8015611aab5780601f10611a8057610100808354040283529160200191611aab565b820191906000526020600020905b815481529060010190602001808311611a8e57829003601f168201915b505050505081565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060018054611aec90614a18565b80601f0160208091040260200160405190810160405280929190818152602001828054611b1890614a18565b8015611b655780601f10611b3a57610100808354040283529160200191611b65565b820191906000526020600020905b815481529060010190602001808311611b4857829003601f168201915b5050505050905090565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611c6a576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401611be7929190614a49565b602060405180830381865afa158015611c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c289190614a87565b611c6957806040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401611c6091906143df565b60405180910390fd5b5b611c748383612d98565b505050565b611c8161296a565b60005b8151811015611d18576000828281518110611ca257611ca1615037565b5b602002602001015190506001601760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550508080611d1090614e55565b915050611c84565b5050565b601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600d60009054906101000a900460ff16611d91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d88906151d6565b60405180910390fd5b601e811115611dd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dcc90615268565b60405180910390fd5b6104bc611ded82600e54612dae90919063ffffffff16565b10611e2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e24906152fa565b60405180910390fd5b600080611e393361114c565b90506000611e46336114bb565b90506000821115611ffc57601e8403611ebd5766071afd498d0000925034611e778585612dc490919063ffffffff16565b1115611eb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eaf90615366565b60405180910390fd5b611ff7565b600f8410611f2957660aa87bee538000925034611ee38585612dc490919063ffffffff16565b1115611f24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1b90615366565b60405180910390fd5b611ff6565b60058410611f9557660e35fa931a0000925034611f4f8585612dc490919063ffffffff16565b1115611f90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8790615366565b60405180910390fd5b611ff5565b6611c37937e08000925034611fb38585612dc490919063ffffffff16565b1115611ff4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611feb90615366565b60405180910390fd5b5b5b5b61237a565b60008214801561200c5750600081115b156121bc57601e840361207d57661550f7dca700009250346120378585612dc490919063ffffffff16565b1115612078576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206f90615366565b60405180910390fd5b6121b7565b600f84106120e9576618de76816d80009250346120a38585612dc490919063ffffffff16565b11156120e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120db90615366565b60405180910390fd5b6121b6565b6005841061215557661c6bf52634000092503461210f8585612dc490919063ffffffff16565b1115612150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161214790615366565b60405180910390fd5b6121b5565b661ff973cafa80009250346121738585612dc490919063ffffffff16565b11156121b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121ab90615366565b60405180910390fd5b5b5b5b612379565b6000821480156121cc5750600081145b1561237857601e840361223d57661ff973cafa80009250346121f78585612dc490919063ffffffff16565b1115612238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161222f90615366565b60405180910390fd5b612377565b600f84106122a957662386f26fc100009250346122638585612dc490919063ffffffff16565b11156122a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161229b90615366565b60405180910390fd5b612376565b600584106123155766271471148780009250346122cf8585612dc490919063ffffffff16565b1115612310576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161230790615366565b60405180910390fd5b612375565b662aa1efb94e00009250346123338585612dc490919063ffffffff16565b1115612374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161236b90615366565b60405180910390fd5b5b5b5b5b5b5b60005b848110156123ce576104bc600e5410156123bb576123a23361239d610ca8565b612a48565b600e60008154809291906123b590614e55565b91905055505b80806123c690614e55565b91505061237d565b5050505050565b6123dd61296a565b60005b81518110156124745760008282815181106123fe576123fd615037565b5b602002602001015190506001601860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050808061246c90614e55565b9150506123e0565b5050565b8360006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156125b7573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036124eb576124e685858585612dda565b6125c4565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401612534929190614a49565b602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125759190614a87565b6125b657336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016125ad91906143df565b60405180910390fd5b5b6125c385858585612dda565b5b5050505050565b60606125d682612808565b60006125e0612e3c565b90506000815111612600576040518060200160405280600081525061262b565b8061260a84612ece565b60405160200161261b9291906153c2565b6040516020818303038152906040525b915050919050565b601e81565b600e5481565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600d60009054906101000a900460ff1681565b6126ed61296a565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361275c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161275390615458565b60405180910390fd5b61276581612cd2565b50565b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612801575061280082612f9c565b5b9050919050565b6128118161307e565b612850576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612847906150b2565b60405180910390fd5b50565b600061285e826118ae565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036128ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128c5906154ea565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166128ed612aaa565b73ffffffffffffffffffffffffffffffffffffffff16148061291c575061291b81612916612aaa565b61263e565b5b61295b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129529061557c565b60405180910390fd5b61296583836130bf565b505050565b612972612aaa565b73ffffffffffffffffffffffffffffffffffffffff16612990611ab3565b73ffffffffffffffffffffffffffffffffffffffff16146129e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129dd906155e8565b60405180910390fd5b565b6129f96129f3612aaa565b82612ab2565b612a38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2f90614f51565b60405180910390fd5b612a43838383613178565b505050565b612a62828260405180602001604052806000815250613471565b5050565b600081600001549050919050565b6001816000016000828254019250508190555050565b612aa583838360405180602001604052806000815250612478565b505050565b600033905090565b600080612abe836118ae565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612b005750612aff818561263e565b5b80612b3e57508373ffffffffffffffffffffffffffffffffffffffff16612b2684610b1d565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b6000612b52826118ae565b9050612b628160008460016134cc565b612b6b826118ae565b90506004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612c918160008460016134de565b5050565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612daa612da3612aaa565b83836134e4565b5050565b60008183612dbc9190614f71565b905092915050565b60008183612dd29190615608565b905092915050565b612deb612de5612aaa565b83612ab2565b612e2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2190614f51565b60405180910390fd5b612e3684848484613650565b50505050565b6060600c8054612e4b90614a18565b80601f0160208091040260200160405190810160405280929190818152602001828054612e7790614a18565b8015612ec45780601f10612e9957610100808354040283529160200191612ec4565b820191906000526020600020905b815481529060010190602001808311612ea757829003601f168201915b5050505050905090565b606060006001612edd846136ac565b01905060008167ffffffffffffffff811115612efc57612efb61449d565b5b6040519080825280601f01601f191660200182016040528015612f2e5781602001600182028036833780820191505090505b509050600082602001820190505b600115612f91578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612f8557612f8461564a565b5b04945060008503612f3c575b819350505050919050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061306757507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806130775750613076826137ff565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166130a083612c95565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16613132836118ae565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b8273ffffffffffffffffffffffffffffffffffffffff16613198826118ae565b73ffffffffffffffffffffffffffffffffffffffff16146131ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131e5906156eb565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361325d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132549061577d565b60405180910390fd5b61326a83838360016134cc565b8273ffffffffffffffffffffffffffffffffffffffff1661328a826118ae565b73ffffffffffffffffffffffffffffffffffffffff16146132e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132d7906156eb565b60405180910390fd5b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461346c83838360016134de565b505050565b61347b8383613869565b6134886000848484613a86565b6134c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134be9061580f565b60405180910390fd5b505050565b6134d884848484613c0d565b50505050565b50505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613552576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135499061587b565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051613643919061426e565b60405180910390a3505050565b61365b848484613178565b61366784848484613a86565b6136a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161369d9061580f565b60405180910390fd5b50505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061370a577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381613700576136ff61564a565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310613747576d04ee2d6d415b85acef8100000000838161373d5761373c61564a565b5b0492506020810190505b662386f26fc10000831061377657662386f26fc10000838161376c5761376b61564a565b5b0492506010810190505b6305f5e100831061379f576305f5e10083816137955761379461564a565b5b0492506008810190505b61271083106137c45761271083816137ba576137b961564a565b5b0492506004810190505b606483106137e757606483816137dd576137dc61564a565b5b0492506002810190505b600a83106137f6576001810190505b80915050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036138d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138cf906158e7565b60405180910390fd5b6138e18161307e565b15613921576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161391890615953565b60405180910390fd5b61392f6000838360016134cc565b6139388161307e565b15613978576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161396f90615953565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613a826000838360016134de565b5050565b6000613aa78473ffffffffffffffffffffffffffffffffffffffff16613d6b565b15613c00578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613ad0612aaa565b8786866040518563ffffffff1660e01b8152600401613af294939291906159c8565b6020604051808303816000875af1925050508015613b2e57506040513d601f19601f82011682018060405250810190613b2b9190615a29565b60015b613bb0573d8060008114613b5e576040519150601f19603f3d011682016040523d82523d6000602084013e613b63565b606091505b506000815103613ba8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b9f9061580f565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613c05565b600190505b949350505050565b613c1984848484613d8e565b6001811115613c5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c5490615ac8565b60405180910390fd5b6000829050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603613ca457613c9f81613eb4565b613ce3565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614613ce257613ce18582613efd565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603613d2557613d208161406a565b613d64565b8473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614613d6357613d62848261413b565b5b5b5050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6001811115613eae57600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614613e225780600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613e1a9190615ae8565b925050819055505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614613ead5780600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613ea59190614f71565b925050819055505b5b50505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b60006001613f0a8461193a565b613f149190615ae8565b9050600060076000848152602001908152602001600020549050818114613ff9576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b6000600160088054905061407e9190615ae8565b90506000600960008481526020019081526020016000205490506000600883815481106140ae576140ad615037565b5b9060005260206000200154905080600883815481106140d0576140cf615037565b5b90600052602060002001819055508160096000838152602001908152602001600020819055506009600085815260200190815260200160002060009055600880548061411f5761411e615b1c565b5b6001900381819060005260206000200160009055905550505050565b60006141468361193a565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614203816141ce565b811461420e57600080fd5b50565b600081359050614220816141fa565b92915050565b60006020828403121561423c5761423b6141c4565b5b600061424a84828501614211565b91505092915050565b60008115159050919050565b61426881614253565b82525050565b6000602082019050614283600083018461425f565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156142c35780820151818401526020810190506142a8565b60008484015250505050565b6000601f19601f8301169050919050565b60006142eb82614289565b6142f58185614294565b93506143058185602086016142a5565b61430e816142cf565b840191505092915050565b6000602082019050818103600083015261433381846142e0565b905092915050565b6000819050919050565b61434e8161433b565b811461435957600080fd5b50565b60008135905061436b81614345565b92915050565b600060208284031215614387576143866141c4565b5b60006143958482850161435c565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006143c98261439e565b9050919050565b6143d9816143be565b82525050565b60006020820190506143f460008301846143d0565b92915050565b614403816143be565b811461440e57600080fd5b50565b600081359050614420816143fa565b92915050565b60006020828403121561443c5761443b6141c4565b5b600061444a84828501614411565b91505092915050565b6000806040838503121561446a576144696141c4565b5b600061447885828601614411565b92505060206144898582860161435c565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6144d5826142cf565b810181811067ffffffffffffffff821117156144f4576144f361449d565b5b80604052505050565b60006145076141ba565b905061451382826144cc565b919050565b600067ffffffffffffffff8211156145335761453261449d565b5b61453c826142cf565b9050602081019050919050565b82818337600083830152505050565b600061456b61456684614518565b6144fd565b90508281526020810184848401111561458757614586614498565b5b614592848285614549565b509392505050565b600082601f8301126145af576145ae614493565b5b81356145bf848260208601614558565b91505092915050565b6000602082840312156145de576145dd6141c4565b5b600082013567ffffffffffffffff8111156145fc576145fb6141c9565b5b6146088482850161459a565b91505092915050565b61461a8161433b565b82525050565b60006020820190506146356000830184614611565b92915050565b600080600060608486031215614654576146536141c4565b5b600061466286828701614411565b935050602061467386828701614411565b92505060406146848682870161435c565b9150509250925092565b6000819050919050565b60006146b36146ae6146a98461439e565b61468e565b61439e565b9050919050565b60006146c582614698565b9050919050565b60006146d7826146ba565b9050919050565b6146e7816146cc565b82525050565b600060208201905061470260008301846146de565b92915050565b61471181614253565b811461471c57600080fd5b50565b60008135905061472e81614708565b92915050565b6000806040838503121561474b5761474a6141c4565b5b600061475985828601614411565b925050602061476a8582860161471f565b9150509250929050565b600067ffffffffffffffff82111561478f5761478e61449d565b5b602082029050602081019050919050565b600080fd5b60006147b86147b384614774565b6144fd565b905080838252602082019050602084028301858111156147db576147da6147a0565b5b835b8181101561480457806147f08882614411565b8452602084019350506020810190506147dd565b5050509392505050565b600082601f83011261482357614822614493565b5b81356148338482602086016147a5565b91505092915050565b600060208284031215614852576148516141c4565b5b600082013567ffffffffffffffff8111156148705761486f6141c9565b5b61487c8482850161480e565b91505092915050565b600067ffffffffffffffff8211156148a05761489f61449d565b5b6148a9826142cf565b9050602081019050919050565b60006148c96148c484614885565b6144fd565b9050828152602081018484840111156148e5576148e4614498565b5b6148f0848285614549565b509392505050565b600082601f83011261490d5761490c614493565b5b813561491d8482602086016148b6565b91505092915050565b600080600080608085870312156149405761493f6141c4565b5b600061494e87828801614411565b945050602061495f87828801614411565b93505060406149708782880161435c565b925050606085013567ffffffffffffffff811115614991576149906141c9565b5b61499d878288016148f8565b91505092959194509250565b600080604083850312156149c0576149bf6141c4565b5b60006149ce85828601614411565b92505060206149df85828601614411565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614a3057607f821691505b602082108103614a4357614a426149e9565b5b50919050565b6000604082019050614a5e60008301856143d0565b614a6b60208301846143d0565b9392505050565b600081519050614a8181614708565b92915050565b600060208284031215614a9d57614a9c6141c4565b5b6000614aab84828501614a72565b91505092915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614b167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614ad9565b614b208683614ad9565b95508019841693508086168417925050509392505050565b6000614b53614b4e614b498461433b565b61468e565b61433b565b9050919050565b6000819050919050565b614b6d83614b38565b614b81614b7982614b5a565b848454614ae6565b825550505050565b600090565b614b96614b89565b614ba1818484614b64565b505050565b5b81811015614bc557614bba600082614b8e565b600181019050614ba7565b5050565b601f821115614c0a57614bdb81614ab4565b614be484614ac9565b81016020851015614bf3578190505b614c07614bff85614ac9565b830182614ba6565b50505b505050565b600082821c905092915050565b6000614c2d60001984600802614c0f565b1980831691505092915050565b6000614c468383614c1c565b9150826002028217905092915050565b614c5f82614289565b67ffffffffffffffff811115614c7857614c7761449d565b5b614c828254614a18565b614c8d828285614bc9565b600060209050601f831160018114614cc05760008415614cae578287015190505b614cb88582614c3a565b865550614d20565b601f198416614cce86614ab4565b60005b82811015614cf657848901518255600182019150602085019450602081019050614cd1565b86831015614d135784890151614d0f601f891682614c1c565b8355505b6001600288020188555050505b505050505050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000614d84602b83614294565b9150614d8f82614d28565b604082019050919050565b60006020820190508181036000830152614db381614d77565b9050919050565b7f4e69636520747279206275737465720000000000000000000000000000000000600082015250565b6000614df0600f83614294565b9150614dfb82614dba565b602082019050919050565b60006020820190508181036000830152614e1f81614de3565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614e608261433b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614e9257614e91614e26565b5b600182019050919050565b600081519050614eac81614345565b92915050565b600060208284031215614ec857614ec76141c4565b5b6000614ed684828501614e9d565b91505092915050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000614f3b602d83614294565b9150614f4682614edf565b604082019050919050565b60006020820190508181036000830152614f6a81614f2e565b9050919050565b6000614f7c8261433b565b9150614f878361433b565b9250828201905080821115614f9f57614f9e614e26565b5b92915050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000615001602c83614294565b915061500c82614fa5565b604082019050919050565b6000602082019050818103600083015261503081614ff4565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b600061509c601883614294565b91506150a782615066565b602082019050919050565b600060208201905081810360008301526150cb8161508f565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b600061512e602983614294565b9150615139826150d2565b604082019050919050565b6000602082019050818103600083015261515d81615121565b9050919050565b7f53616c65206d7573742062652061637469766520746f206d696e74204d696c6160008201527f6479730000000000000000000000000000000000000000000000000000000000602082015250565b60006151c0602383614294565b91506151cb82615164565b604082019050919050565b600060208201905081810360008301526151ef816151b3565b9050919050565b7f43616e206f6e6c79206d696e7420757020746f20333020746f6b656e7320617460008201527f20612074696d6500000000000000000000000000000000000000000000000000602082015250565b6000615252602783614294565b915061525d826151f6565b604082019050919050565b6000602082019050818103600083015261528181615245565b9050919050565b7f507572636861736520776f756c6420657863656564206d617820737570706c7960008201527f206f66204d696c61647973000000000000000000000000000000000000000000602082015250565b60006152e4602b83614294565b91506152ef82615288565b604082019050919050565b60006020820190508181036000830152615313816152d7565b9050919050565b7f45746865722076616c75652073656e74206973206e6f7420636f727265637400600082015250565b6000615350601f83614294565b915061535b8261531a565b602082019050919050565b6000602082019050818103600083015261537f81615343565b9050919050565b600081905092915050565b600061539c82614289565b6153a68185615386565b93506153b68185602086016142a5565b80840191505092915050565b60006153ce8285615391565b91506153da8284615391565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000615442602683614294565b915061544d826153e6565b604082019050919050565b6000602082019050818103600083015261547181615435565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006154d4602183614294565b91506154df82615478565b604082019050919050565b60006020820190508181036000830152615503816154c7565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000615566603d83614294565b91506155718261550a565b604082019050919050565b6000602082019050818103600083015261559581615559565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006155d2602083614294565b91506155dd8261559c565b602082019050919050565b60006020820190508181036000830152615601816155c5565b9050919050565b60006156138261433b565b915061561e8361433b565b925082820261562c8161433b565b9150828204841483151761564357615642614e26565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b60006156d5602583614294565b91506156e082615679565b604082019050919050565b60006020820190508181036000830152615704816156c8565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000615767602483614294565b91506157728261570b565b604082019050919050565b600060208201905081810360008301526157968161575a565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b60006157f9603283614294565b91506158048261579d565b604082019050919050565b60006020820190508181036000830152615828816157ec565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000615865601983614294565b91506158708261582f565b602082019050919050565b6000602082019050818103600083015261589481615858565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b60006158d1602083614294565b91506158dc8261589b565b602082019050919050565b60006020820190508181036000830152615900816158c4565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b600061593d601c83614294565b915061594882615907565b602082019050919050565b6000602082019050818103600083015261596c81615930565b9050919050565b600081519050919050565b600082825260208201905092915050565b600061599a82615973565b6159a4818561597e565b93506159b48185602086016142a5565b6159bd816142cf565b840191505092915050565b60006080820190506159dd60008301876143d0565b6159ea60208301866143d0565b6159f76040830185614611565b8181036060830152615a09818461598f565b905095945050505050565b600081519050615a23816141fa565b92915050565b600060208284031215615a3f57615a3e6141c4565b5b6000615a4d84828501615a14565b91505092915050565b7f455243373231456e756d657261626c653a20636f6e736563757469766520747260008201527f616e7366657273206e6f7420737570706f727465640000000000000000000000602082015250565b6000615ab2603583614294565b9150615abd82615a56565b604082019050919050565b60006020820190508181036000830152615ae181615aa5565b9050919050565b6000615af38261433b565b9150615afe8361433b565b9250828203905081811115615b1657615b15614e26565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220a9be460dd2aeee2582de153d35c38c0765f1f0a287b2d5f8c68cbb2b24735c4e64736f6c63430008110033

Deployed Bytecode

0x6080604052600436106102725760003560e01c806355f804b31161014f578063abaf648f116100c1578063e01559ca1161007a578063e01559ca14610967578063e380231514610992578063e985e9c5146109bd578063eb8d2444146109fa578063f2fde38b14610a25578063fc48984e14610a4e57610272565b8063abaf648f14610868578063ac54f0e814610891578063b1e283de146108bc578063b6d8e86f146108d8578063b88d4fde14610901578063c87b56dd1461092a57610272565b8063715018a611610113578063715018a61461076a5780637d5fcf9c146107815780638b83df45146107be5780638da5cb5b146107e957806395d89b4114610814578063a22cb4651461083f57610272565b806355f804b3146106715780635854d9491461069a5780636352211e146106c5578063635df4ab1461070257806370a082311461072d57610272565b80633494f1bf116101e857806341f43434116101ac57806341f434341461054f57806342842e0e1461057a57806342966c68146105a35780634b01570a146105cc5780634f6ccce71461060957806355e4ef9a1461064657610272565b80633494f1bf1461046a5780633c79f889146104a75780633ccfd60b146104d25780633eab9435146104e957806340d097c31461052657610272565b8063109695231161023a578063109695231461038257806318160ddd146103ab57806323b872dd146103d65780632f745c59146103ff578063323ab4741461043c57806334918dfd1461045357610272565b806301ffc9a71461027757806306fdde03146102b4578063081812fc146102df5780630920a7851461031c578063095ea7b314610359575b600080fd5b34801561028357600080fd5b5061029e60048036038101906102999190614226565b610a79565b6040516102ab919061426e565b60405180910390f35b3480156102c057600080fd5b506102c9610a8b565b6040516102d69190614319565b60405180910390f35b3480156102eb57600080fd5b5061030660048036038101906103019190614371565b610b1d565b60405161031391906143df565b60405180910390f35b34801561032857600080fd5b50610343600480360381019061033e9190614426565b610b63565b604051610350919061426e565b60405180910390f35b34801561036557600080fd5b50610380600480360381019061037b9190614453565b610b83565b005b34801561038e57600080fd5b506103a960048036038101906103a491906145c8565b610c8d565b005b3480156103b757600080fd5b506103c0610ca8565b6040516103cd9190614620565b60405180910390f35b3480156103e257600080fd5b506103fd60048036038101906103f8919061463b565b610cb5565b005b34801561040b57600080fd5b5061042660048036038101906104219190614453565b610e05565b6040516104339190614620565b60405180910390f35b34801561044857600080fd5b50610451610eaa565b005b34801561045f57600080fd5b50610468611118565b005b34801561047657600080fd5b50610491600480360381019061048c9190614426565b61114c565b60405161049e9190614620565b60405180910390f35b3480156104b357600080fd5b506104bc611232565b6040516104c991906143df565b60405180910390f35b3480156104de57600080fd5b506104e7611258565b005b3480156104f557600080fd5b50610510600480360381019061050b9190614426565b6112af565b60405161051d919061426e565b60405180910390f35b34801561053257600080fd5b5061054d60048036038101906105489190614426565b6112cf565b005b34801561055b57600080fd5b506105646112fd565b60405161057191906146ed565b60405180910390f35b34801561058657600080fd5b506105a1600480360381019061059c919061463b565b61130f565b005b3480156105af57600080fd5b506105ca60048036038101906105c59190614371565b61145f565b005b3480156105d857600080fd5b506105f360048036038101906105ee9190614426565b6114bb565b6040516106009190614620565b60405180910390f35b34801561061557600080fd5b50610630600480360381019061062b9190614371565b61176e565b60405161063d9190614620565b60405180910390f35b34801561065257600080fd5b5061065b6117df565b60405161066891906143df565b60405180910390f35b34801561067d57600080fd5b50610698600480360381019061069391906145c8565b611805565b005b3480156106a657600080fd5b506106af611820565b6040516106bc9190614319565b60405180910390f35b3480156106d157600080fd5b506106ec60048036038101906106e79190614371565b6118ae565b6040516106f991906143df565b60405180910390f35b34801561070e57600080fd5b50610717611934565b6040516107249190614620565b60405180910390f35b34801561073957600080fd5b50610754600480360381019061074f9190614426565b61193a565b6040516107619190614620565b60405180910390f35b34801561077657600080fd5b5061077f6119f1565b005b34801561078d57600080fd5b506107a860048036038101906107a39190614426565b611a05565b6040516107b5919061426e565b60405180910390f35b3480156107ca57600080fd5b506107d3611a25565b6040516107e09190614319565b60405180910390f35b3480156107f557600080fd5b506107fe611ab3565b60405161080b91906143df565b60405180910390f35b34801561082057600080fd5b50610829611add565b6040516108369190614319565b60405180910390f35b34801561084b57600080fd5b5061086660048036038101906108619190614734565b611b6f565b005b34801561087457600080fd5b5061088f600480360381019061088a919061483c565b611c79565b005b34801561089d57600080fd5b506108a6611d1c565b6040516108b391906143df565b60405180910390f35b6108d660048036038101906108d19190614371565b611d42565b005b3480156108e457600080fd5b506108ff60048036038101906108fa919061483c565b6123d5565b005b34801561090d57600080fd5b5061092860048036038101906109239190614926565b612478565b005b34801561093657600080fd5b50610951600480360381019061094c9190614371565b6125cb565b60405161095e9190614319565b60405180910390f35b34801561097357600080fd5b5061097c612633565b6040516109899190614620565b60405180910390f35b34801561099e57600080fd5b506109a7612638565b6040516109b49190614620565b60405180910390f35b3480156109c957600080fd5b506109e460048036038101906109df91906149a9565b61263e565b6040516109f1919061426e565b60405180910390f35b348015610a0657600080fd5b50610a0f6126d2565b604051610a1c919061426e565b60405180910390f35b348015610a3157600080fd5b50610a4c6004803603810190610a479190614426565b6126e5565b005b348015610a5a57600080fd5b50610a63612768565b604051610a7091906143df565b60405180910390f35b6000610a848261278e565b9050919050565b606060008054610a9a90614a18565b80601f0160208091040260200160405190810160405280929190818152602001828054610ac690614a18565b8015610b135780601f10610ae857610100808354040283529160200191610b13565b820191906000526020600020905b815481529060010190602001808311610af657829003601f168201915b5050505050905090565b6000610b2882612808565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60176020528060005260406000206000915054906101000a900460ff1681565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115610c7e576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401610bfb929190614a49565b602060405180830381865afa158015610c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3c9190614a87565b610c7d57806040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401610c7491906143df565b60405180910390fd5b5b610c888383612853565b505050565b610c9561296a565b80600b9081610ca49190614c56565b5050565b6000600880549050905090565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115610df3573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d2757610d228484846129e8565b610dff565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401610d70929190614a49565b602060405180830381865afa158015610d8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db19190614a87565b610df257336040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401610de991906143df565b60405180910390fd5b5b610dfe8484846129e8565b5b50505050565b6000610e108361193a565b8210610e51576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e4890614d9a565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b600080610eb63361114c565b9050601760003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610f1357601e91506110ca565b601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610fc6576000601860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600291506110c9565b6000811180156110205750601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16155b15611086576001601960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550600191506110c8565b60006110c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110be90614e06565b60405180910390fd5b5b5b5b60005b82811080156110e457506104bc6110e2610ca8565b105b156111135760006110f3610ca8565b90506110ff3382612a48565b50808061110b90614e55565b9150506110cd565b505050565b61112061296a565b600d60009054906101000a900460ff1615600d60006101000a81548160ff021916908315150217905550565b60008060009050601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231846040518263ffffffff1660e01b81526004016111ae91906143df565b602060405180830381865afa9250505080156111e857506040513d601f19601f820116820180604052508101906111e59190614eb2565b60015b611224573d8060008114611218576040519150601f19603f3d011682016040523d82523d6000602084013e61121d565b606091505b5050611229565b809150505b80915050919050565b601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61126061296a565b60004790503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156112ab573d6000803e3d6000fd5b5050565b60196020528060005260406000206000915054906101000a900460ff1681565b6112d761296a565b60006112e3601a612a66565b90506112ef601a612a74565b6112f98282612a48565b5050565b6daaeb6d7670e522a718067333cd4e81565b8260006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b111561144d573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036113815761137c848484612a8a565b611459565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b81526004016113ca929190614a49565b602060405180830381865afa1580156113e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140b9190614a87565b61144c57336040517fede71dcc00000000000000000000000000000000000000000000000000000000815260040161144391906143df565b60405180910390fd5b5b611458848484612a8a565b5b50505050565b61147061146a612aaa565b82612ab2565b6114af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114a690614f51565b60405180910390fd5b6114b881612b47565b50565b60008060009050601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231846040518263ffffffff1660e01b815260040161151d91906143df565b602060405180830381865afa92505050801561155757506040513d601f19601f820116820180604052508101906115549190614eb2565b60015b611593573d8060008114611587576040519150601f19603f3d011682016040523d82523d6000602084013e61158c565b606091505b50506115a3565b808261159f9190614f71565b9150505b601560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231846040518263ffffffff1660e01b81526004016115fe91906143df565b602060405180830381865afa92505050801561163857506040513d601f19601f820116820180604052508101906116359190614eb2565b60015b611674573d8060008114611668576040519150601f19603f3d011682016040523d82523d6000602084013e61166d565b606091505b5050611684565b80826116809190614f71565b9150505b601660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231846040518263ffffffff1660e01b81526004016116df91906143df565b602060405180830381865afa92505050801561171957506040513d601f19601f820116820180604052508101906117169190614eb2565b60015b611755573d8060008114611749576040519150601f19603f3d011682016040523d82523d6000602084013e61174e565b606091505b5050611765565b80826117619190614f71565b9150505b80915050919050565b6000611778610ca8565b82106117b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b090615017565b60405180910390fd5b600882815481106117cd576117cc615037565b5b90600052602060002001549050919050565b601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61180d61296a565b80600c908161181c9190614c56565b5050565b600b805461182d90614a18565b80601f016020809104026020016040519081016040528092919081815260200182805461185990614a18565b80156118a65780601f1061187b576101008083540402835291602001916118a6565b820191906000526020600020905b81548152906001019060200180831161188957829003601f168201915b505050505081565b6000806118ba83612c95565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361192b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611922906150b2565b60405180910390fd5b80915050919050565b6104bc81565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036119aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119a190615144565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6119f961296a565b611a036000612cd2565b565b60186020528060005260406000206000915054906101000a900460ff1681565b600c8054611a3290614a18565b80601f0160208091040260200160405190810160405280929190818152602001828054611a5e90614a18565b8015611aab5780601f10611a8057610100808354040283529160200191611aab565b820191906000526020600020905b815481529060010190602001808311611a8e57829003601f168201915b505050505081565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060018054611aec90614a18565b80601f0160208091040260200160405190810160405280929190818152602001828054611b1890614a18565b8015611b655780601f10611b3a57610100808354040283529160200191611b65565b820191906000526020600020905b815481529060010190602001808311611b4857829003601f168201915b5050505050905090565b8160006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b1115611c6a576daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430836040518363ffffffff1660e01b8152600401611be7929190614a49565b602060405180830381865afa158015611c04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c289190614a87565b611c6957806040517fede71dcc000000000000000000000000000000000000000000000000000000008152600401611c6091906143df565b60405180910390fd5b5b611c748383612d98565b505050565b611c8161296a565b60005b8151811015611d18576000828281518110611ca257611ca1615037565b5b602002602001015190506001601760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550508080611d1090614e55565b915050611c84565b5050565b601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600d60009054906101000a900460ff16611d91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d88906151d6565b60405180910390fd5b601e811115611dd5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dcc90615268565b60405180910390fd5b6104bc611ded82600e54612dae90919063ffffffff16565b10611e2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e24906152fa565b60405180910390fd5b600080611e393361114c565b90506000611e46336114bb565b90506000821115611ffc57601e8403611ebd5766071afd498d0000925034611e778585612dc490919063ffffffff16565b1115611eb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eaf90615366565b60405180910390fd5b611ff7565b600f8410611f2957660aa87bee538000925034611ee38585612dc490919063ffffffff16565b1115611f24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1b90615366565b60405180910390fd5b611ff6565b60058410611f9557660e35fa931a0000925034611f4f8585612dc490919063ffffffff16565b1115611f90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f8790615366565b60405180910390fd5b611ff5565b6611c37937e08000925034611fb38585612dc490919063ffffffff16565b1115611ff4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611feb90615366565b60405180910390fd5b5b5b5b61237a565b60008214801561200c5750600081115b156121bc57601e840361207d57661550f7dca700009250346120378585612dc490919063ffffffff16565b1115612078576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206f90615366565b60405180910390fd5b6121b7565b600f84106120e9576618de76816d80009250346120a38585612dc490919063ffffffff16565b11156120e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120db90615366565b60405180910390fd5b6121b6565b6005841061215557661c6bf52634000092503461210f8585612dc490919063ffffffff16565b1115612150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161214790615366565b60405180910390fd5b6121b5565b661ff973cafa80009250346121738585612dc490919063ffffffff16565b11156121b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121ab90615366565b60405180910390fd5b5b5b5b612379565b6000821480156121cc5750600081145b1561237857601e840361223d57661ff973cafa80009250346121f78585612dc490919063ffffffff16565b1115612238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161222f90615366565b60405180910390fd5b612377565b600f84106122a957662386f26fc100009250346122638585612dc490919063ffffffff16565b11156122a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161229b90615366565b60405180910390fd5b612376565b600584106123155766271471148780009250346122cf8585612dc490919063ffffffff16565b1115612310576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161230790615366565b60405180910390fd5b612375565b662aa1efb94e00009250346123338585612dc490919063ffffffff16565b1115612374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161236b90615366565b60405180910390fd5b5b5b5b5b5b5b60005b848110156123ce576104bc600e5410156123bb576123a23361239d610ca8565b612a48565b600e60008154809291906123b590614e55565b91905055505b80806123c690614e55565b91505061237d565b5050505050565b6123dd61296a565b60005b81518110156124745760008282815181106123fe576123fd615037565b5b602002602001015190506001601860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050808061246c90614e55565b9150506123e0565b5050565b8360006daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff163b11156125b7573373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036124eb576124e685858585612dda565b6125c4565b6daaeb6d7670e522a718067333cd4e73ffffffffffffffffffffffffffffffffffffffff1663c617113430336040518363ffffffff1660e01b8152600401612534929190614a49565b602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125759190614a87565b6125b657336040517fede71dcc0000000000000000000000000000000000000000000000000000000081526004016125ad91906143df565b60405180910390fd5b5b6125c385858585612dda565b5b5050505050565b60606125d682612808565b60006125e0612e3c565b90506000815111612600576040518060200160405280600081525061262b565b8061260a84612ece565b60405160200161261b9291906153c2565b6040516020818303038152906040525b915050919050565b601e81565b600e5481565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600d60009054906101000a900460ff1681565b6126ed61296a565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361275c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161275390615458565b60405180910390fd5b61276581612cd2565b50565b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612801575061280082612f9c565b5b9050919050565b6128118161307e565b612850576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612847906150b2565b60405180910390fd5b50565b600061285e826118ae565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036128ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128c5906154ea565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166128ed612aaa565b73ffffffffffffffffffffffffffffffffffffffff16148061291c575061291b81612916612aaa565b61263e565b5b61295b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129529061557c565b60405180910390fd5b61296583836130bf565b505050565b612972612aaa565b73ffffffffffffffffffffffffffffffffffffffff16612990611ab3565b73ffffffffffffffffffffffffffffffffffffffff16146129e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129dd906155e8565b60405180910390fd5b565b6129f96129f3612aaa565b82612ab2565b612a38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2f90614f51565b60405180910390fd5b612a43838383613178565b505050565b612a62828260405180602001604052806000815250613471565b5050565b600081600001549050919050565b6001816000016000828254019250508190555050565b612aa583838360405180602001604052806000815250612478565b505050565b600033905090565b600080612abe836118ae565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612b005750612aff818561263e565b5b80612b3e57508373ffffffffffffffffffffffffffffffffffffffff16612b2684610b1d565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b6000612b52826118ae565b9050612b628160008460016134cc565b612b6b826118ae565b90506004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612c918160008460016134de565b5050565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b612daa612da3612aaa565b83836134e4565b5050565b60008183612dbc9190614f71565b905092915050565b60008183612dd29190615608565b905092915050565b612deb612de5612aaa565b83612ab2565b612e2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2190614f51565b60405180910390fd5b612e3684848484613650565b50505050565b6060600c8054612e4b90614a18565b80601f0160208091040260200160405190810160405280929190818152602001828054612e7790614a18565b8015612ec45780601f10612e9957610100808354040283529160200191612ec4565b820191906000526020600020905b815481529060010190602001808311612ea757829003601f168201915b5050505050905090565b606060006001612edd846136ac565b01905060008167ffffffffffffffff811115612efc57612efb61449d565b5b6040519080825280601f01601f191660200182016040528015612f2e5781602001600182028036833780820191505090505b509050600082602001820190505b600115612f91578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581612f8557612f8461564a565b5b04945060008503612f3c575b819350505050919050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061306757507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806130775750613076826137ff565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166130a083612c95565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16613132836118ae565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b8273ffffffffffffffffffffffffffffffffffffffff16613198826118ae565b73ffffffffffffffffffffffffffffffffffffffff16146131ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131e5906156eb565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361325d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132549061577d565b60405180910390fd5b61326a83838360016134cc565b8273ffffffffffffffffffffffffffffffffffffffff1661328a826118ae565b73ffffffffffffffffffffffffffffffffffffffff16146132e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132d7906156eb565b60405180910390fd5b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461346c83838360016134de565b505050565b61347b8383613869565b6134886000848484613a86565b6134c7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016134be9061580f565b60405180910390fd5b505050565b6134d884848484613c0d565b50505050565b50505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603613552576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135499061587b565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051613643919061426e565b60405180910390a3505050565b61365b848484613178565b61366784848484613a86565b6136a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161369d9061580f565b60405180910390fd5b50505050565b600080600090507a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000831061370a577a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008381613700576136ff61564a565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310613747576d04ee2d6d415b85acef8100000000838161373d5761373c61564a565b5b0492506020810190505b662386f26fc10000831061377657662386f26fc10000838161376c5761376b61564a565b5b0492506010810190505b6305f5e100831061379f576305f5e10083816137955761379461564a565b5b0492506008810190505b61271083106137c45761271083816137ba576137b961564a565b5b0492506004810190505b606483106137e757606483816137dd576137dc61564a565b5b0492506002810190505b600a83106137f6576001810190505b80915050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036138d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138cf906158e7565b60405180910390fd5b6138e18161307e565b15613921576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161391890615953565b60405180910390fd5b61392f6000838360016134cc565b6139388161307e565b15613978576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161396f90615953565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4613a826000838360016134de565b5050565b6000613aa78473ffffffffffffffffffffffffffffffffffffffff16613d6b565b15613c00578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613ad0612aaa565b8786866040518563ffffffff1660e01b8152600401613af294939291906159c8565b6020604051808303816000875af1925050508015613b2e57506040513d601f19601f82011682018060405250810190613b2b9190615a29565b60015b613bb0573d8060008114613b5e576040519150601f19603f3d011682016040523d82523d6000602084013e613b63565b606091505b506000815103613ba8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b9f9061580f565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614915050613c05565b600190505b949350505050565b613c1984848484613d8e565b6001811115613c5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c5490615ac8565b60405180910390fd5b6000829050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1603613ca457613c9f81613eb4565b613ce3565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614613ce257613ce18582613efd565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603613d2557613d208161406a565b613d64565b8473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614613d6357613d62848261413b565b5b5b5050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6001811115613eae57600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614613e225780600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613e1a9190615ae8565b925050819055505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614613ead5780600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613ea59190614f71565b925050819055505b5b50505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b60006001613f0a8461193a565b613f149190615ae8565b9050600060076000848152602001908152602001600020549050818114613ff9576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b6000600160088054905061407e9190615ae8565b90506000600960008481526020019081526020016000205490506000600883815481106140ae576140ad615037565b5b9060005260206000200154905080600883815481106140d0576140cf615037565b5b90600052602060002001819055508160096000838152602001908152602001600020819055506009600085815260200190815260200160002060009055600880548061411f5761411e615b1c565b5b6001900381819060005260206000200160009055905550505050565b60006141468361193a565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b614203816141ce565b811461420e57600080fd5b50565b600081359050614220816141fa565b92915050565b60006020828403121561423c5761423b6141c4565b5b600061424a84828501614211565b91505092915050565b60008115159050919050565b61426881614253565b82525050565b6000602082019050614283600083018461425f565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156142c35780820151818401526020810190506142a8565b60008484015250505050565b6000601f19601f8301169050919050565b60006142eb82614289565b6142f58185614294565b93506143058185602086016142a5565b61430e816142cf565b840191505092915050565b6000602082019050818103600083015261433381846142e0565b905092915050565b6000819050919050565b61434e8161433b565b811461435957600080fd5b50565b60008135905061436b81614345565b92915050565b600060208284031215614387576143866141c4565b5b60006143958482850161435c565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006143c98261439e565b9050919050565b6143d9816143be565b82525050565b60006020820190506143f460008301846143d0565b92915050565b614403816143be565b811461440e57600080fd5b50565b600081359050614420816143fa565b92915050565b60006020828403121561443c5761443b6141c4565b5b600061444a84828501614411565b91505092915050565b6000806040838503121561446a576144696141c4565b5b600061447885828601614411565b92505060206144898582860161435c565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6144d5826142cf565b810181811067ffffffffffffffff821117156144f4576144f361449d565b5b80604052505050565b60006145076141ba565b905061451382826144cc565b919050565b600067ffffffffffffffff8211156145335761453261449d565b5b61453c826142cf565b9050602081019050919050565b82818337600083830152505050565b600061456b61456684614518565b6144fd565b90508281526020810184848401111561458757614586614498565b5b614592848285614549565b509392505050565b600082601f8301126145af576145ae614493565b5b81356145bf848260208601614558565b91505092915050565b6000602082840312156145de576145dd6141c4565b5b600082013567ffffffffffffffff8111156145fc576145fb6141c9565b5b6146088482850161459a565b91505092915050565b61461a8161433b565b82525050565b60006020820190506146356000830184614611565b92915050565b600080600060608486031215614654576146536141c4565b5b600061466286828701614411565b935050602061467386828701614411565b92505060406146848682870161435c565b9150509250925092565b6000819050919050565b60006146b36146ae6146a98461439e565b61468e565b61439e565b9050919050565b60006146c582614698565b9050919050565b60006146d7826146ba565b9050919050565b6146e7816146cc565b82525050565b600060208201905061470260008301846146de565b92915050565b61471181614253565b811461471c57600080fd5b50565b60008135905061472e81614708565b92915050565b6000806040838503121561474b5761474a6141c4565b5b600061475985828601614411565b925050602061476a8582860161471f565b9150509250929050565b600067ffffffffffffffff82111561478f5761478e61449d565b5b602082029050602081019050919050565b600080fd5b60006147b86147b384614774565b6144fd565b905080838252602082019050602084028301858111156147db576147da6147a0565b5b835b8181101561480457806147f08882614411565b8452602084019350506020810190506147dd565b5050509392505050565b600082601f83011261482357614822614493565b5b81356148338482602086016147a5565b91505092915050565b600060208284031215614852576148516141c4565b5b600082013567ffffffffffffffff8111156148705761486f6141c9565b5b61487c8482850161480e565b91505092915050565b600067ffffffffffffffff8211156148a05761489f61449d565b5b6148a9826142cf565b9050602081019050919050565b60006148c96148c484614885565b6144fd565b9050828152602081018484840111156148e5576148e4614498565b5b6148f0848285614549565b509392505050565b600082601f83011261490d5761490c614493565b5b813561491d8482602086016148b6565b91505092915050565b600080600080608085870312156149405761493f6141c4565b5b600061494e87828801614411565b945050602061495f87828801614411565b93505060406149708782880161435c565b925050606085013567ffffffffffffffff811115614991576149906141c9565b5b61499d878288016148f8565b91505092959194509250565b600080604083850312156149c0576149bf6141c4565b5b60006149ce85828601614411565b92505060206149df85828601614411565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680614a3057607f821691505b602082108103614a4357614a426149e9565b5b50919050565b6000604082019050614a5e60008301856143d0565b614a6b60208301846143d0565b9392505050565b600081519050614a8181614708565b92915050565b600060208284031215614a9d57614a9c6141c4565b5b6000614aab84828501614a72565b91505092915050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302614b167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82614ad9565b614b208683614ad9565b95508019841693508086168417925050509392505050565b6000614b53614b4e614b498461433b565b61468e565b61433b565b9050919050565b6000819050919050565b614b6d83614b38565b614b81614b7982614b5a565b848454614ae6565b825550505050565b600090565b614b96614b89565b614ba1818484614b64565b505050565b5b81811015614bc557614bba600082614b8e565b600181019050614ba7565b5050565b601f821115614c0a57614bdb81614ab4565b614be484614ac9565b81016020851015614bf3578190505b614c07614bff85614ac9565b830182614ba6565b50505b505050565b600082821c905092915050565b6000614c2d60001984600802614c0f565b1980831691505092915050565b6000614c468383614c1c565b9150826002028217905092915050565b614c5f82614289565b67ffffffffffffffff811115614c7857614c7761449d565b5b614c828254614a18565b614c8d828285614bc9565b600060209050601f831160018114614cc05760008415614cae578287015190505b614cb88582614c3a565b865550614d20565b601f198416614cce86614ab4565b60005b82811015614cf657848901518255600182019150602085019450602081019050614cd1565b86831015614d135784890151614d0f601f891682614c1c565b8355505b6001600288020188555050505b505050505050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000614d84602b83614294565b9150614d8f82614d28565b604082019050919050565b60006020820190508181036000830152614db381614d77565b9050919050565b7f4e69636520747279206275737465720000000000000000000000000000000000600082015250565b6000614df0600f83614294565b9150614dfb82614dba565b602082019050919050565b60006020820190508181036000830152614e1f81614de3565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614e608261433b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614e9257614e91614e26565b5b600182019050919050565b600081519050614eac81614345565b92915050565b600060208284031215614ec857614ec76141c4565b5b6000614ed684828501614e9d565b91505092915050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000614f3b602d83614294565b9150614f4682614edf565b604082019050919050565b60006020820190508181036000830152614f6a81614f2e565b9050919050565b6000614f7c8261433b565b9150614f878361433b565b9250828201905080821115614f9f57614f9e614e26565b5b92915050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b6000615001602c83614294565b915061500c82614fa5565b604082019050919050565b6000602082019050818103600083015261503081614ff4565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b600061509c601883614294565b91506150a782615066565b602082019050919050565b600060208201905081810360008301526150cb8161508f565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b600061512e602983614294565b9150615139826150d2565b604082019050919050565b6000602082019050818103600083015261515d81615121565b9050919050565b7f53616c65206d7573742062652061637469766520746f206d696e74204d696c6160008201527f6479730000000000000000000000000000000000000000000000000000000000602082015250565b60006151c0602383614294565b91506151cb82615164565b604082019050919050565b600060208201905081810360008301526151ef816151b3565b9050919050565b7f43616e206f6e6c79206d696e7420757020746f20333020746f6b656e7320617460008201527f20612074696d6500000000000000000000000000000000000000000000000000602082015250565b6000615252602783614294565b915061525d826151f6565b604082019050919050565b6000602082019050818103600083015261528181615245565b9050919050565b7f507572636861736520776f756c6420657863656564206d617820737570706c7960008201527f206f66204d696c61647973000000000000000000000000000000000000000000602082015250565b60006152e4602b83614294565b91506152ef82615288565b604082019050919050565b60006020820190508181036000830152615313816152d7565b9050919050565b7f45746865722076616c75652073656e74206973206e6f7420636f727265637400600082015250565b6000615350601f83614294565b915061535b8261531a565b602082019050919050565b6000602082019050818103600083015261537f81615343565b9050919050565b600081905092915050565b600061539c82614289565b6153a68185615386565b93506153b68185602086016142a5565b80840191505092915050565b60006153ce8285615391565b91506153da8284615391565b91508190509392505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000615442602683614294565b915061544d826153e6565b604082019050919050565b6000602082019050818103600083015261547181615435565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006154d4602183614294565b91506154df82615478565b604082019050919050565b60006020820190508181036000830152615503816154c7565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000615566603d83614294565b91506155718261550a565b604082019050919050565b6000602082019050818103600083015261559581615559565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006155d2602083614294565b91506155dd8261559c565b602082019050919050565b60006020820190508181036000830152615601816155c5565b9050919050565b60006156138261433b565b915061561e8361433b565b925082820261562c8161433b565b9150828204841483151761564357615642614e26565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b60006156d5602583614294565b91506156e082615679565b604082019050919050565b60006020820190508181036000830152615704816156c8565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000615767602483614294565b91506157728261570b565b604082019050919050565b600060208201905081810360008301526157968161575a565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b60006157f9603283614294565b91506158048261579d565b604082019050919050565b60006020820190508181036000830152615828816157ec565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000615865601983614294565b91506158708261582f565b602082019050919050565b6000602082019050818103600083015261589481615858565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b60006158d1602083614294565b91506158dc8261589b565b602082019050919050565b60006020820190508181036000830152615900816158c4565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b600061593d601c83614294565b915061594882615907565b602082019050919050565b6000602082019050818103600083015261596c81615930565b9050919050565b600081519050919050565b600082825260208201905092915050565b600061599a82615973565b6159a4818561597e565b93506159b48185602086016142a5565b6159bd816142cf565b840191505092915050565b60006080820190506159dd60008301876143d0565b6159ea60208301866143d0565b6159f76040830185614611565b8181036060830152615a09818461598f565b905095945050505050565b600081519050615a23816141fa565b92915050565b600060208284031215615a3f57615a3e6141c4565b5b6000615a4d84828501615a14565b91505092915050565b7f455243373231456e756d657261626c653a20636f6e736563757469766520747260008201527f616e7366657273206e6f7420737570706f727465640000000000000000000000602082015250565b6000615ab2603583614294565b9150615abd82615a56565b604082019050919050565b60006020820190508181036000830152615ae181615aa5565b9050919050565b6000615af38261433b565b9150615afe8361433b565b9250828203905081811115615b1657615b15614e26565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea2646970667358221220a9be460dd2aeee2582de153d35c38c0765f1f0a287b2d5f8c68cbb2b24735c4e64736f6c63430008110033

Deployed Bytecode Sourcemap

145158:10981:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;148257:212;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122402:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;123914:171;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;146193:48;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;146988:175;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;149081:134;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;139767:113;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;147171:181;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;139435:256;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;151273:731;;;;;;;;;;;;;:::i;:::-;;152016:89;;;;;;;;;;;;;:::i;:::-;;149398:384;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;145826:77;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;149227:140;;;;;;;;;;;;;:::i;:::-;;146303:44;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;146503:180;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;11891:143;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;147360:189;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;137852:242;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;149816:893;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;139957:233;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;145662:75;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152117:96;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;145301:43;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122112:223;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;145434:49;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;121843:207;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;100700:103;;;;;;;;;;;;;:::i;:::-;;146248:48;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;145351:26;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;100052:87;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;122571:104;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;146786:194;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;150746:242;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;145744:75;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;152221:3915;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;151023:242;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;147557:246;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;122746:281;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;145384:43;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;145529:38;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;124383:164;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;145490:32;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;100958:201;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;145576:73;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;148257:212;148396:4;148425:36;148449:11;148425:23;:36::i;:::-;148418:43;;148257:212;;;:::o;122402:100::-;122456:13;122489:5;122482:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122402:100;:::o;123914:171::-;123990:7;124010:23;124025:7;124010:14;:23::i;:::-;124053:15;:24;124069:7;124053:24;;;;;;;;;;;;;;;;;;;;;124046:31;;123914:171;;;:::o;146193:48::-;;;;;;;;;;;;;;;;;;;;;;:::o;146988:175::-;147102:8;13933:1;11991:42;13885:45;;;:49;13881:225;;;11991:42;13956;;;14007:4;14014:8;13956:67;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13951:144;;14070:8;14051:28;;;;;;;;;;;:::i;:::-;;;;;;;;13951:144;13881:225;147123:32:::1;147137:8;147147:7;147123:13;:32::i;:::-;146988:175:::0;;;:::o;149081:134::-;99938:13;:11;:13::i;:::-;149193:14:::1;149166:24;:41;;;;;;:::i;:::-;;149081:134:::0;:::o;139767:113::-;139828:7;139855:10;:17;;;;139848:24;;139767:113;:::o;147171:181::-;147290:4;13187:1;11991:42;13139:45;;;:49;13135:539;;;13428:10;13420:18;;:4;:18;;;13416:85;;147307:37:::1;147326:4;147332:2;147336:7;147307:18;:37::i;:::-;13479:7:::0;;13416:85;11991:42;13520;;;13571:4;13578:10;13520:69;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13515:148;;13636:10;13617:30;;;;;;;;;;;:::i;:::-;;;;;;;;13515:148;13135:539;147307:37:::1;147326:4;147332:2;147336:7;147307:18;:37::i;:::-;147171:181:::0;;;;;:::o;139435:256::-;139532:7;139568:23;139585:5;139568:16;:23::i;:::-;139560:5;:31;139552:87;;;;;;;;;;;;:::i;:::-;;;;;;;;;139657:12;:19;139670:5;139657:19;;;;;;;;;;;;;;;:26;139677:5;139657:26;;;;;;;;;;;;139650:33;;139435:256;;;;:::o;151273:731::-;151321:15;151347;151365:29;151383:10;151365:17;:29::i;:::-;151347:47;;151409:16;:28;151426:10;151409:28;;;;;;;;;;;;;;;;;;;;;;;;;151405:410;;;151466:2;151453:15;;151405:410;;;151490:16;:28;151507:10;151490:28;;;;;;;;;;;;;;;;;;;;;;;;;151486:329;;;151565:5;151534:16;:28;151551:10;151534:28;;;;;;;;;;;;;;;;:36;;;;;;;;;;;;;;;;;;151598:1;151585:14;;151486:329;;;151631:1;151621:7;:11;:40;;;;;151637:12;:24;151650:10;151637:24;;;;;;;;;;;;;;;;;;;;;;;;;151636:25;151621:40;151617:198;;;151704:4;151677:12;:24;151690:10;151677:24;;;;;;;;;;;;;;;;:31;;;;;;;;;;;;;;;;;;151736:1;151723:14;;151617:198;;;151778:5;151770:33;;;;;;;;;;;;:::i;:::-;;;;;;;;;151617:198;151486:329;151405:410;151825:6;151842:155;151858:10;151854:1;:14;:38;;;;;151888:4;151872:13;:11;:13::i;:::-;:20;151854:38;151842:155;;;151914:11;151928:13;:11;:13::i;:::-;151914:27;;151956:29;151966:10;151978:6;151956:9;:29::i;:::-;151899:98;151894:3;;;;;:::i;:::-;;;;151842:155;;;151310:694;;;151273:731::o;152016:89::-;99938:13;:11;:13::i;:::-;152085:12:::1;;;;;;;;;;;152084:13;152069:12;;:28;;;;;;;;;;;;;;;;;;152016:89::o:0;149398:384::-;149462:7;149482:16;149501:1;149482:20;;149517:6;;;;;;;;;;;:16;;;149534:6;149517:24;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;149513:236;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;149676:73;149513:236;;;149646:17;149635:28;;149542:133;149513:236;149766:8;149759:15;;;149398:384;;;:::o;145826:77::-;;;;;;;;;;;;;:::o;149227:140::-;99938:13;:11;:13::i;:::-;149275:12:::1;149290:21;149275:36;;149330:10;149322:28;;:37;149351:7;149322:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;149264:103;149227:140::o:0;146303:44::-;;;;;;;;;;;;;;;;;;;;;;:::o;146503:180::-;99938:13;:11;:13::i;:::-;146561:15:::1;146579:25;:15;:23;:25::i;:::-;146561:43;;146615:27;:15;:25;:27::i;:::-;146653:22;146663:2;146667:7;146653:9;:22::i;:::-;146550:133;146503:180:::0;:::o;11891:143::-;11991:42;11891:143;:::o;147360:189::-;147483:4;13187:1;11991:42;13139:45;;;:49;13135:539;;;13428:10;13420:18;;:4;:18;;;13416:85;;147500:41:::1;147523:4;147529:2;147533:7;147500:22;:41::i;:::-;13479:7:::0;;13416:85;11991:42;13520;;;13571:4;13578:10;13520:69;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13515:148;;13636:10;13617:30;;;;;;;;;;;:::i;:::-;;;;;;;;13515:148;13135:539;147500:41:::1;147523:4;147529:2;147533:7;147500:22;:41::i;:::-;147360:189:::0;;;;;:::o;137852:242::-;137970:41;137989:12;:10;:12::i;:::-;138003:7;137970:18;:41::i;:::-;137962:99;;;;;;;;;;;;:::i;:::-;;;;;;;;;138072:14;138078:7;138072:5;:14::i;:::-;137852:242;:::o;149816:893::-;149880:7;149929:16;149948:1;149929:20;;149964:8;;;;;;;;;;;:18;;;149983:6;149964:26;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;149960:235;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;150122:73;149960:235;;;150094:15;150082:27;;;;;:::i;:::-;;;149991:130;149960:235;150209:8;;;;;;;;;;;:18;;;150228:6;150209:26;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;150205:233;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;150365:73;150205:233;;;150338:14;150326:26;;;;;:::i;:::-;;;150236:128;150205:233;150452:3;;;;;;;;;;;:13;;;150466:6;150452:21;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;150448:228;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;150603:73;150448:228;;;150576:14;150564:26;;;;;:::i;:::-;;;150474:128;150448:228;150693:8;150686:15;;;149816:893;;;:::o;139957:233::-;140032:7;140068:30;:28;:30::i;:::-;140060:5;:38;140052:95;;;;;;;;;;;;:::i;:::-;;;;;;;;;140165:10;140176:5;140165:17;;;;;;;;:::i;:::-;;;;;;;;;;140158:24;;139957:233;;;:::o;145662:75::-;;;;;;;;;;;;;:::o;152117:96::-;99938:13;:11;:13::i;:::-;152198:7:::1;152188;:17;;;;;;:::i;:::-;;152117:96:::0;:::o;145301:43::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;122112:223::-;122184:7;122204:13;122220:17;122229:7;122220:8;:17::i;:::-;122204:33;;122273:1;122256:19;;:5;:19;;;122248:56;;;;;;;;;;;;:::i;:::-;;;;;;;;;122322:5;122315:12;;;122112:223;;;:::o;145434:49::-;145479:4;145434:49;:::o;121843:207::-;121915:7;121960:1;121943:19;;:5;:19;;;121935:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;122026:9;:16;122036:5;122026:16;;;;;;;;;;;;;;;;122019:23;;121843:207;;;:::o;100700:103::-;99938:13;:11;:13::i;:::-;100765:30:::1;100792:1;100765:18;:30::i;:::-;100700:103::o:0;146248:48::-;;;;;;;;;;;;;;;;;;;;;;:::o;145351:26::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;100052:87::-;100098:7;100125:6;;;;;;;;;;;100118:13;;100052:87;:::o;122571:104::-;122627:13;122660:7;122653:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122571:104;:::o;146786:194::-;146908:8;13933:1;11991:42;13885:45;;;:49;13881:225;;;11991:42;13956;;;14007:4;14014:8;13956:67;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13951:144;;14070:8;14051:28;;;;;;;;;;;:::i;:::-;;;;;;;;13951:144;13881:225;146929:43:::1;146953:8;146963;146929:23;:43::i;:::-;146786:194:::0;;;:::o;150746:242::-;99938:13;:11;:13::i;:::-;150828:9:::1;150824:156;150847:5;:12;150843:1;:16;150824:156;;;150881:22;150906:5;150912:1;150906:8;;;;;;;;:::i;:::-;;;;;;;;150881:33;;150964:4;150929:16;:32;150946:14;150929:32;;;;;;;;;;;;;;;;:39;;;;;;;;;;;;;;;;;;150866:114;150861:3;;;;;:::i;:::-;;;;150824:156;;;;150746:242:::0;:::o;145744:75::-;;;;;;;;;;;;;:::o;152221:3915::-;152300:12;;;;;;;;;;;152292:60;;;;;;;;;;;;:::i;:::-;;;;;;;;;145425:2;152371:14;:35;;152363:87;;;;;;;;;;;;:::i;:::-;;;;;;;;;145479:4;152469:39;152493:14;152469:19;;:23;;:39;;;;:::i;:::-;:60;152461:116;;;;;;;;;;;;:::i;:::-;;;;;;;;;152588:19;152618:27;152648:29;152666:10;152648:17;:29::i;:::-;152618:59;;152688:27;152718:29;152736:10;152718:17;:29::i;:::-;152688:59;;152848:1;152826:19;:23;152822:3073;;;152887:2;152869:14;:20;152865:858;;152924:16;152910:30;;153016:9;152981:31;152997:14;152981:11;:15;;:31;;;;:::i;:::-;:44;;152973:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;152865:858;;;153105:2;153087:14;:20;153083:640;;153142:16;153128:30;;153234:9;153199:31;153215:14;153199:11;:15;;:31;;;;:::i;:::-;:44;;153191:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;153083:640;;;153323:1;153305:14;:19;153301:422;;153359:16;153345:30;;153451:9;153416:31;153432:14;153416:11;:15;;:31;;;;:::i;:::-;:44;;153408:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;153301:422;;;153551:16;153537:30;;153662:9;153627:31;153643:14;153627:11;:15;;:31;;;;:::i;:::-;:44;;153619:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;153301:422;153083:640;152865:858;152822:3073;;;153890:1;153867:19;:24;:51;;;;;153917:1;153895:19;:23;153867:51;153863:2032;;;153954:2;153936:14;:20;153932:856;;153991:16;153977:30;;154082:9;154047:31;154063:14;154047:11;:15;;:31;;;;:::i;:::-;:44;;154039:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;153932:856;;;154171:2;154153:14;:20;154149:639;;154208:16;154194:30;;154299:9;154264:31;154280:14;154264:11;:15;;:31;;;;:::i;:::-;:44;;154256:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;154149:639;;;154388:1;154370:14;:19;154366:422;;154424:16;154410:30;;154515:9;154480:31;154496:14;154480:11;:15;;:31;;;;:::i;:::-;:44;;154472:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;154366:422;;;154615:16;154601:30;;154727:9;154692:31;154708:14;154692:11;:15;;:31;;;;:::i;:::-;:44;;154684:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;154366:422;154149:639;153932:856;153863:2032;;;154980:1;154957:19;:24;:52;;;;;155008:1;154985:19;:24;154957:52;154953:942;;;155046:2;155028:14;:20;155024:860;;155083:16;155069:30;;155175:9;155140:31;155156:14;155140:11;:15;;:31;;;;:::i;:::-;:44;;155132:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;155024:860;;;155264:2;155246:14;:20;155242:642;;155301:17;155287:31;;155393:9;155358:31;155374:14;155358:11;:15;;:31;;;;:::i;:::-;:44;;155350:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;155242:642;;;155482:1;155464:14;:19;155460:424;;155518:17;155504:31;;155610:9;155575:31;155591:14;155575:11;:15;;:31;;;;:::i;:::-;:44;;155567:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;155460:424;;;155710:17;155696:31;;155823:9;155788:31;155804:14;155788:11;:15;;:31;;;;:::i;:::-;:44;;155780:88;;;;;;;;;;;;:::i;:::-;;;;;;;;;155460:424;155242:642;155024:860;154953:942;153863:2032;152822:3073;155909:6;155905:224;155925:14;155921:1;:18;155905:224;;;145479:4;155965:19;;:40;155961:157;;;156026:36;156036:10;156048:13;:11;:13::i;:::-;156026:9;:36::i;:::-;156081:19;;:21;;;;;;;;;:::i;:::-;;;;;;155961:157;155941:3;;;;;:::i;:::-;;;;155905:224;;;;152281:3855;;;152221:3915;:::o;151023:242::-;99938:13;:11;:13::i;:::-;151105:9:::1;151101:156;151124:5;:12;151120:1;:16;151101:156;;;151158:22;151183:5;151189:1;151183:8;;;;;;;;:::i;:::-;;;;;;;;151158:33;;151241:4;151206:16;:32;151223:14;151206:32;;;;;;;;;;;;;;;;:39;;;;;;;;;;;;;;;;;;151143:114;151138:3;;;;;:::i;:::-;;;;151101:156;;;;151023:242:::0;:::o;147557:246::-;147726:4;13187:1;11991:42;13139:45;;;:49;13135:539;;;13428:10;13420:18;;:4;:18;;;13416:85;;147748:47:::1;147771:4;147777:2;147781:7;147790:4;147748:22;:47::i;:::-;13479:7:::0;;13416:85;11991:42;13520;;;13571:4;13578:10;13520:69;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13515:148;;13636:10;13617:30;;;;;;;;;;;:::i;:::-;;;;;;;;13515:148;13135:539;147748:47:::1;147771:4;147777:2;147781:7;147790:4;147748:22;:47::i;:::-;147557:246:::0;;;;;;:::o;122746:281::-;122819:13;122845:23;122860:7;122845:14;:23::i;:::-;122881:21;122905:10;:8;:10::i;:::-;122881:34;;122957:1;122939:7;122933:21;:25;:86;;;;;;;;;;;;;;;;;122985:7;122994:18;:7;:16;:18::i;:::-;122968:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;122933:86;122926:93;;;122746:281;;;:::o;145384:43::-;145425:2;145384:43;:::o;145529:38::-;;;;:::o;124383:164::-;124480:4;124504:18;:25;124523:5;124504:25;;;;;;;;;;;;;;;:35;124530:8;124504:35;;;;;;;;;;;;;;;;;;;;;;;;;124497:42;;124383:164;;;;:::o;145490:32::-;;;;;;;;;;;;;:::o;100958:201::-;99938:13;:11;:13::i;:::-;101067:1:::1;101047:22;;:8;:22;;::::0;101039:73:::1;;;;;;;;;;;;:::i;:::-;;;;;;;;;101123:28;101142:8;101123:18;:28::i;:::-;100958:201:::0;:::o;145576:73::-;;;;;;;;;;;;;:::o;139127:224::-;139229:4;139268:35;139253:50;;;:11;:50;;;;:90;;;;139307:36;139331:11;139307:23;:36::i;:::-;139253:90;139246:97;;139127:224;;;:::o;133733:135::-;133815:16;133823:7;133815;:16::i;:::-;133807:53;;;;;;;;;;;;:::i;:::-;;;;;;;;;133733:135;:::o;123432:416::-;123513:13;123529:23;123544:7;123529:14;:23::i;:::-;123513:39;;123577:5;123571:11;;:2;:11;;;123563:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;123671:5;123655:21;;:12;:10;:12::i;:::-;:21;;;:62;;;;123680:37;123697:5;123704:12;:10;:12::i;:::-;123680:16;:37::i;:::-;123655:62;123633:173;;;;;;;;;;;;:::i;:::-;;;;;;;;;123819:21;123828:2;123832:7;123819:8;:21::i;:::-;123502:346;123432:416;;:::o;100217:132::-;100292:12;:10;:12::i;:::-;100281:23;;:7;:5;:7::i;:::-;:23;;;100273:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;100217:132::o;124614:335::-;124809:41;124828:12;:10;:12::i;:::-;124842:7;124809:18;:41::i;:::-;124801:99;;;;;;;;;;;;:::i;:::-;;;;;;;;;124913:28;124923:4;124929:2;124933:7;124913:9;:28::i;:::-;124614:335;;;:::o;128237:110::-;128313:26;128323:2;128327:7;128313:26;;;;;;;;;;;;:9;:26::i;:::-;128237:110;;:::o;22509:114::-;22574:7;22601;:14;;;22594:21;;22509:114;;;:::o;22631:127::-;22738:1;22720:7;:14;;;:19;;;;;;;;;;;22631:127;:::o;125020:185::-;125158:39;125175:4;125181:2;125185:7;125158:39;;;;;;;;;;;;:16;:39::i;:::-;125020:185;;;:::o;98603:98::-;98656:7;98683:10;98676:17;;98603:98;:::o;127631:264::-;127724:4;127741:13;127757:23;127772:7;127757:14;:23::i;:::-;127741:39;;127810:5;127799:16;;:7;:16;;;:52;;;;127819:32;127836:5;127843:7;127819:16;:32::i;:::-;127799:52;:87;;;;127879:7;127855:31;;:20;127867:7;127855:11;:20::i;:::-;:31;;;127799:87;127791:96;;;127631:264;;;;:::o;130510:783::-;130570:13;130586:23;130601:7;130586:14;:23::i;:::-;130570:39;;130622:51;130643:5;130658:1;130662:7;130671:1;130622:20;:51::i;:::-;130786:23;130801:7;130786:14;:23::i;:::-;130778:31;;130857:15;:24;130873:7;130857:24;;;;;;;;;;;;130850:31;;;;;;;;;;;131122:1;131102:9;:16;131112:5;131102:16;;;;;;;;;;;;;;;;:21;;;;;;;;;;;131152:7;:16;131160:7;131152:16;;;;;;;;;;;;131145:23;;;;;;;;;;;131214:7;131210:1;131186:36;;131195:5;131186:36;;;;;;;;;;;;131235:50;131255:5;131270:1;131274:7;131283:1;131235:19;:50::i;:::-;130559:734;130510:783;:::o;126906:117::-;126972:7;126999;:16;127007:7;126999:16;;;;;;;;;;;;;;;;;;;;;126992:23;;126906:117;;;:::o;101319:191::-;101393:16;101412:6;;;;;;;;;;;101393:25;;101438:8;101429:6;;:17;;;;;;;;;;;;;;;;;;101493:8;101462:40;;101483:8;101462:40;;;;;;;;;;;;101382:128;101319:191;:::o;124157:155::-;124252:52;124271:12;:10;:12::i;:::-;124285:8;124295;124252:18;:52::i;:::-;124157:155;;:::o;17472:98::-;17530:7;17561:1;17557;:5;;;;:::i;:::-;17550:12;;17472:98;;;;:::o;18210:::-;18268:7;18299:1;18295;:5;;;;:::i;:::-;18288:12;;18210:98;;;;:::o;125276:322::-;125450:41;125469:12;:10;:12::i;:::-;125483:7;125450:18;:41::i;:::-;125442:99;;;;;;;;;;;;:::i;:::-;;;;;;;;;125552:38;125566:4;125572:2;125576:7;125585:4;125552:13;:38::i;:::-;125276:322;;;;:::o;148133:116::-;148201:13;148234:7;148227:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;148133:116;:::o;96030:716::-;96086:13;96137:14;96174:1;96154:17;96165:5;96154:10;:17::i;:::-;:21;96137:38;;96190:20;96224:6;96213:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96190:41;;96246:11;96375:6;96371:2;96367:15;96359:6;96355:28;96348:35;;96412:288;96419:4;96412:288;;;96444:5;;;;;;;;96586:8;96581:2;96574:5;96570:14;96565:30;96560:3;96552:44;96642:2;96633:11;;;;;;:::i;:::-;;;;;96676:1;96667:5;:10;96412:288;96663:21;96412:288;96721:6;96714:13;;;;;96030:716;;;:::o;121474:305::-;121576:4;121628:25;121613:40;;;:11;:40;;;;:105;;;;121685:33;121670:48;;;:11;:48;;;;121613:105;:158;;;;121735:36;121759:11;121735:23;:36::i;:::-;121613:158;121593:178;;121474:305;;;:::o;127336:128::-;127401:4;127454:1;127425:31;;:17;127434:7;127425:8;:17::i;:::-;:31;;;;127418:38;;127336:128;;;:::o;133012:174::-;133114:2;133087:15;:24;133103:7;133087:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;133170:7;133166:2;133132:46;;133141:23;133156:7;133141:14;:23::i;:::-;133132:46;;;;;;;;;;;;133012:174;;:::o;131630:1263::-;131789:4;131762:31;;:23;131777:7;131762:14;:23::i;:::-;:31;;;131754:81;;;;;;;;;;;;:::i;:::-;;;;;;;;;131868:1;131854:16;;:2;:16;;;131846:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;131924:42;131945:4;131951:2;131955:7;131964:1;131924:20;:42::i;:::-;132096:4;132069:31;;:23;132084:7;132069:14;:23::i;:::-;:31;;;132061:81;;;;;;;;;;;;:::i;:::-;;;;;;;;;132214:15;:24;132230:7;132214:24;;;;;;;;;;;;132207:31;;;;;;;;;;;132709:1;132690:9;:15;132700:4;132690:15;;;;;;;;;;;;;;;;:20;;;;;;;;;;;132742:1;132725:9;:13;132735:2;132725:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;132784:2;132765:7;:16;132773:7;132765:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;132823:7;132819:2;132804:27;;132813:4;132804:27;;;;;;;;;;;;132844:41;132864:4;132870:2;132874:7;132883:1;132844:19;:41::i;:::-;131630:1263;;;:::o;128574:319::-;128703:18;128709:2;128713:7;128703:5;:18::i;:::-;128754:53;128785:1;128789:2;128793:7;128802:4;128754:22;:53::i;:::-;128732:153;;;;;;;;;;;;:::i;:::-;;;;;;;;;128574:319;;;:::o;147881:244::-;148056:61;148083:4;148089:2;148093:12;148107:9;148056:26;:61::i;:::-;147881:244;;;;:::o;137149:158::-;;;;;:::o;133329:315::-;133484:8;133475:17;;:5;:17;;;133467:55;;;;;;;;;;;;:::i;:::-;;;;;;;;;133571:8;133533:18;:25;133552:5;133533:25;;;;;;;;;;;;;;;:35;133559:8;133533:35;;;;;;;;;;;;;;;;:46;;;;;;;;;;;;;;;;;;133617:8;133595:41;;133610:5;133595:41;;;133627:8;133595:41;;;;;;:::i;:::-;;;;;;;;133329:315;;;:::o;126479:313::-;126635:28;126645:4;126651:2;126655:7;126635:9;:28::i;:::-;126682:47;126705:4;126711:2;126715:7;126724:4;126682:22;:47::i;:::-;126674:110;;;;;;;;;;;;:::i;:::-;;;;;;;;;126479:313;;;;:::o;92896:922::-;92949:7;92969:14;92986:1;92969:18;;93036:6;93027:5;:15;93023:102;;93072:6;93063:15;;;;;;:::i;:::-;;;;;93107:2;93097:12;;;;93023:102;93152:6;93143:5;:15;93139:102;;93188:6;93179:15;;;;;;:::i;:::-;;;;;93223:2;93213:12;;;;93139:102;93268:6;93259:5;:15;93255:102;;93304:6;93295:15;;;;;;:::i;:::-;;;;;93339:2;93329:12;;;;93255:102;93384:5;93375;:14;93371:99;;93419:5;93410:14;;;;;;:::i;:::-;;;;;93453:1;93443:11;;;;93371:99;93497:5;93488;:14;93484:99;;93532:5;93523:14;;;;;;:::i;:::-;;;;;93566:1;93556:11;;;;93484:99;93610:5;93601;:14;93597:99;;93645:5;93636:14;;;;;;:::i;:::-;;;;;93679:1;93669:11;;;;93597:99;93723:5;93714;:14;93710:66;;93759:1;93749:11;;;;93710:66;93804:6;93797:13;;;92896:922;;;:::o;112906:157::-;112991:4;113030:25;113015:40;;;:11;:40;;;;113008:47;;112906:157;;;:::o;129229:942::-;129323:1;129309:16;;:2;:16;;;129301:61;;;;;;;;;;;;:::i;:::-;;;;;;;;;129382:16;129390:7;129382;:16::i;:::-;129381:17;129373:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;129444:48;129473:1;129477:2;129481:7;129490:1;129444:20;:48::i;:::-;129591:16;129599:7;129591;:16::i;:::-;129590:17;129582:58;;;;;;;;;;;;:::i;:::-;;;;;;;;;130006:1;129989:9;:13;129999:2;129989:13;;;;;;;;;;;;;;;;:18;;;;;;;;;;;130050:2;130031:7;:16;130039:7;130031:16;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;130095:7;130091:2;130070:33;;130087:1;130070:33;;;;;;;;;;;;130116:47;130144:1;130148:2;130152:7;130161:1;130116:19;:47::i;:::-;129229:942;;:::o;134432:853::-;134586:4;134607:15;:2;:13;;;:15::i;:::-;134603:675;;;134659:2;134643:36;;;134680:12;:10;:12::i;:::-;134694:4;134700:7;134709:4;134643:71;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;134639:584;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134901:1;134884:6;:13;:18;134880:328;;134927:60;;;;;;;;;;:::i;:::-;;;;;;;;134880:328;135158:6;135152:13;135143:6;135139:2;135135:15;135128:38;134639:584;134775:41;;;134765:51;;;:6;:51;;;;134758:58;;;;;134603:675;135262:4;135255:11;;134432:853;;;;;;;:::o;140264:915::-;140441:61;140468:4;140474:2;140478:12;140492:9;140441:26;:61::i;:::-;140531:1;140519:9;:13;140515:222;;;140662:63;;;;;;;;;;:::i;:::-;;;;;;;;140515:222;140749:15;140767:12;140749:30;;140812:1;140796:18;;:4;:18;;;140792:187;;140831:40;140863:7;140831:31;:40::i;:::-;140792:187;;;140901:2;140893:10;;:4;:10;;;140889:90;;140920:47;140953:4;140959:7;140920:32;:47::i;:::-;140889:90;140792:187;141007:1;140993:16;;:2;:16;;;140989:183;;141026:45;141063:7;141026:36;:45::i;:::-;140989:183;;;141099:4;141093:10;;:2;:10;;;141089:83;;141120:40;141148:2;141152:7;141120:27;:40::i;:::-;141089:83;140989:183;140430:749;140264:915;;;;:::o;102750:326::-;102810:4;103067:1;103045:7;:19;;;:23;103038:30;;102750:326;;;:::o;136017:410::-;136207:1;136195:9;:13;136191:229;;;136245:1;136229:18;;:4;:18;;;136225:87;;136287:9;136268;:15;136278:4;136268:15;;;;;;;;;;;;;;;;:28;;;;;;;:::i;:::-;;;;;;;;136225:87;136344:1;136330:16;;:2;:16;;;136326:83;;136384:9;136367;:13;136377:2;136367:13;;;;;;;;;;;;;;;;:26;;;;;;;:::i;:::-;;;;;;;;136326:83;136191:229;136017:410;;;;:::o;141902:164::-;142006:10;:17;;;;141979:15;:24;141995:7;141979:24;;;;;;;;;;;:44;;;;142034:10;142050:7;142034:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;141902:164;:::o;142693:988::-;142959:22;143009:1;142984:22;143001:4;142984:16;:22::i;:::-;:26;;;;:::i;:::-;142959:51;;143021:18;143042:17;:26;143060:7;143042:26;;;;;;;;;;;;143021:47;;143189:14;143175:10;:28;143171:328;;143220:19;143242:12;:18;143255:4;143242:18;;;;;;;;;;;;;;;:34;143261:14;143242:34;;;;;;;;;;;;143220:56;;143326:11;143293:12;:18;143306:4;143293:18;;;;;;;;;;;;;;;:30;143312:10;143293:30;;;;;;;;;;;:44;;;;143443:10;143410:17;:30;143428:11;143410:30;;;;;;;;;;;:43;;;;143205:294;143171:328;143595:17;:26;143613:7;143595:26;;;;;;;;;;;143588:33;;;143639:12;:18;143652:4;143639:18;;;;;;;;;;;;;;;:34;143658:14;143639:34;;;;;;;;;;;143632:41;;;142774:907;;142693:988;;:::o;143976:1079::-;144229:22;144274:1;144254:10;:17;;;;:21;;;;:::i;:::-;144229:46;;144286:18;144307:15;:24;144323:7;144307:24;;;;;;;;;;;;144286:45;;144658:19;144680:10;144691:14;144680:26;;;;;;;;:::i;:::-;;;;;;;;;;144658:48;;144744:11;144719:10;144730;144719:22;;;;;;;;:::i;:::-;;;;;;;;;:36;;;;144855:10;144824:15;:28;144840:11;144824:28;;;;;;;;;;;:41;;;;144996:15;:24;145012:7;144996:24;;;;;;;;;;;144989:31;;;145031:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;144047:1008;;;143976:1079;:::o;141480:221::-;141565:14;141582:20;141599:2;141582:16;:20::i;:::-;141565:37;;141640:7;141613:12;:16;141626:2;141613:16;;;;;;;;;;;;;;;:24;141630:6;141613:24;;;;;;;;;;;:34;;;;141687:6;141658:17;:26;141676:7;141658:26;;;;;;;;;;;:35;;;;141554:147;141480:221;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:149;370:7;410:66;403:5;399:78;388:89;;334:149;;;:::o;489:120::-;561:23;578:5;561:23;:::i;:::-;554:5;551:34;541:62;;599:1;596;589:12;541:62;489:120;:::o;615:137::-;660:5;698:6;685:20;676:29;;714:32;740:5;714:32;:::i;:::-;615:137;;;;:::o;758:327::-;816:6;865:2;853:9;844:7;840:23;836:32;833:119;;;871:79;;:::i;:::-;833:119;991:1;1016:52;1060:7;1051:6;1040:9;1036:22;1016:52;:::i;:::-;1006:62;;962:116;758:327;;;;:::o;1091:90::-;1125:7;1168:5;1161:13;1154:21;1143:32;;1091:90;;;:::o;1187:109::-;1268:21;1283:5;1268:21;:::i;:::-;1263:3;1256:34;1187:109;;:::o;1302:210::-;1389:4;1427:2;1416:9;1412:18;1404:26;;1440:65;1502:1;1491:9;1487:17;1478:6;1440:65;:::i;:::-;1302:210;;;;:::o;1518:99::-;1570:6;1604:5;1598:12;1588:22;;1518:99;;;:::o;1623:169::-;1707:11;1741:6;1736:3;1729:19;1781:4;1776:3;1772:14;1757:29;;1623:169;;;;:::o;1798:246::-;1879:1;1889:113;1903:6;1900:1;1897:13;1889:113;;;1988:1;1983:3;1979:11;1973:18;1969:1;1964:3;1960:11;1953:39;1925:2;1922:1;1918:10;1913:15;;1889:113;;;2036:1;2027:6;2022:3;2018:16;2011:27;1860:184;1798:246;;;:::o;2050:102::-;2091:6;2142:2;2138:7;2133:2;2126:5;2122:14;2118:28;2108:38;;2050:102;;;:::o;2158:377::-;2246:3;2274:39;2307:5;2274:39;:::i;:::-;2329:71;2393:6;2388:3;2329:71;:::i;:::-;2322:78;;2409:65;2467:6;2462:3;2455:4;2448:5;2444:16;2409:65;:::i;:::-;2499:29;2521:6;2499:29;:::i;:::-;2494:3;2490:39;2483:46;;2250:285;2158:377;;;;:::o;2541:313::-;2654:4;2692:2;2681:9;2677:18;2669:26;;2741:9;2735:4;2731:20;2727:1;2716:9;2712:17;2705:47;2769:78;2842:4;2833:6;2769:78;:::i;:::-;2761:86;;2541:313;;;;:::o;2860:77::-;2897:7;2926:5;2915:16;;2860:77;;;:::o;2943:122::-;3016:24;3034:5;3016:24;:::i;:::-;3009:5;3006:35;2996:63;;3055:1;3052;3045:12;2996:63;2943:122;:::o;3071:139::-;3117:5;3155:6;3142:20;3133:29;;3171:33;3198:5;3171:33;:::i;:::-;3071:139;;;;:::o;3216:329::-;3275:6;3324:2;3312:9;3303:7;3299:23;3295:32;3292:119;;;3330:79;;:::i;:::-;3292:119;3450:1;3475:53;3520:7;3511:6;3500:9;3496:22;3475:53;:::i;:::-;3465:63;;3421:117;3216:329;;;;:::o;3551:126::-;3588:7;3628:42;3621:5;3617:54;3606:65;;3551:126;;;:::o;3683:96::-;3720:7;3749:24;3767:5;3749:24;:::i;:::-;3738:35;;3683:96;;;:::o;3785:118::-;3872:24;3890:5;3872:24;:::i;:::-;3867:3;3860:37;3785:118;;:::o;3909:222::-;4002:4;4040:2;4029:9;4025:18;4017:26;;4053:71;4121:1;4110:9;4106:17;4097:6;4053:71;:::i;:::-;3909:222;;;;:::o;4137:122::-;4210:24;4228:5;4210:24;:::i;:::-;4203:5;4200:35;4190:63;;4249:1;4246;4239:12;4190:63;4137:122;:::o;4265:139::-;4311:5;4349:6;4336:20;4327:29;;4365:33;4392:5;4365:33;:::i;:::-;4265:139;;;;:::o;4410:329::-;4469:6;4518:2;4506:9;4497:7;4493:23;4489:32;4486:119;;;4524:79;;:::i;:::-;4486:119;4644:1;4669:53;4714:7;4705:6;4694:9;4690:22;4669:53;:::i;:::-;4659:63;;4615:117;4410:329;;;;:::o;4745:474::-;4813:6;4821;4870:2;4858:9;4849:7;4845:23;4841:32;4838:119;;;4876:79;;:::i;:::-;4838:119;4996:1;5021:53;5066:7;5057:6;5046:9;5042:22;5021:53;:::i;:::-;5011:63;;4967:117;5123:2;5149:53;5194:7;5185:6;5174:9;5170:22;5149:53;:::i;:::-;5139:63;;5094:118;4745:474;;;;;:::o;5225:117::-;5334:1;5331;5324:12;5348:117;5457:1;5454;5447:12;5471:180;5519:77;5516:1;5509:88;5616:4;5613:1;5606:15;5640:4;5637:1;5630:15;5657:281;5740:27;5762:4;5740:27;:::i;:::-;5732:6;5728:40;5870:6;5858:10;5855:22;5834:18;5822:10;5819:34;5816:62;5813:88;;;5881:18;;:::i;:::-;5813:88;5921:10;5917:2;5910:22;5700:238;5657:281;;:::o;5944:129::-;5978:6;6005:20;;:::i;:::-;5995:30;;6034:33;6062:4;6054:6;6034:33;:::i;:::-;5944:129;;;:::o;6079:308::-;6141:4;6231:18;6223:6;6220:30;6217:56;;;6253:18;;:::i;:::-;6217:56;6291:29;6313:6;6291:29;:::i;:::-;6283:37;;6375:4;6369;6365:15;6357:23;;6079:308;;;:::o;6393:146::-;6490:6;6485:3;6480;6467:30;6531:1;6522:6;6517:3;6513:16;6506:27;6393:146;;;:::o;6545:425::-;6623:5;6648:66;6664:49;6706:6;6664:49;:::i;:::-;6648:66;:::i;:::-;6639:75;;6737:6;6730:5;6723:21;6775:4;6768:5;6764:16;6813:3;6804:6;6799:3;6795:16;6792:25;6789:112;;;6820:79;;:::i;:::-;6789:112;6910:54;6957:6;6952:3;6947;6910:54;:::i;:::-;6629:341;6545:425;;;;;:::o;6990:340::-;7046:5;7095:3;7088:4;7080:6;7076:17;7072:27;7062:122;;7103:79;;:::i;:::-;7062:122;7220:6;7207:20;7245:79;7320:3;7312:6;7305:4;7297:6;7293:17;7245:79;:::i;:::-;7236:88;;7052:278;6990:340;;;;:::o;7336:509::-;7405:6;7454:2;7442:9;7433:7;7429:23;7425:32;7422:119;;;7460:79;;:::i;:::-;7422:119;7608:1;7597:9;7593:17;7580:31;7638:18;7630:6;7627:30;7624:117;;;7660:79;;:::i;:::-;7624:117;7765:63;7820:7;7811:6;7800:9;7796:22;7765:63;:::i;:::-;7755:73;;7551:287;7336:509;;;;:::o;7851:118::-;7938:24;7956:5;7938:24;:::i;:::-;7933:3;7926:37;7851:118;;:::o;7975:222::-;8068:4;8106:2;8095:9;8091:18;8083:26;;8119:71;8187:1;8176:9;8172:17;8163:6;8119:71;:::i;:::-;7975:222;;;;:::o;8203:619::-;8280:6;8288;8296;8345:2;8333:9;8324:7;8320:23;8316:32;8313:119;;;8351:79;;:::i;:::-;8313:119;8471:1;8496:53;8541:7;8532:6;8521:9;8517:22;8496:53;:::i;:::-;8486:63;;8442:117;8598:2;8624:53;8669:7;8660:6;8649:9;8645:22;8624:53;:::i;:::-;8614:63;;8569:118;8726:2;8752:53;8797:7;8788:6;8777:9;8773:22;8752:53;:::i;:::-;8742:63;;8697:118;8203:619;;;;;:::o;8828:60::-;8856:3;8877:5;8870:12;;8828:60;;;:::o;8894:142::-;8944:9;8977:53;8995:34;9004:24;9022:5;9004:24;:::i;:::-;8995:34;:::i;:::-;8977:53;:::i;:::-;8964:66;;8894:142;;;:::o;9042:126::-;9092:9;9125:37;9156:5;9125:37;:::i;:::-;9112:50;;9042:126;;;:::o;9174:157::-;9255:9;9288:37;9319:5;9288:37;:::i;:::-;9275:50;;9174:157;;;:::o;9337:193::-;9455:68;9517:5;9455:68;:::i;:::-;9450:3;9443:81;9337:193;;:::o;9536:284::-;9660:4;9698:2;9687:9;9683:18;9675:26;;9711:102;9810:1;9799:9;9795:17;9786:6;9711:102;:::i;:::-;9536:284;;;;:::o;9826:116::-;9896:21;9911:5;9896:21;:::i;:::-;9889:5;9886:32;9876:60;;9932:1;9929;9922:12;9876:60;9826:116;:::o;9948:133::-;9991:5;10029:6;10016:20;10007:29;;10045:30;10069:5;10045:30;:::i;:::-;9948:133;;;;:::o;10087:468::-;10152:6;10160;10209:2;10197:9;10188:7;10184:23;10180:32;10177:119;;;10215:79;;:::i;:::-;10177:119;10335:1;10360:53;10405:7;10396:6;10385:9;10381:22;10360:53;:::i;:::-;10350:63;;10306:117;10462:2;10488:50;10530:7;10521:6;10510:9;10506:22;10488:50;:::i;:::-;10478:60;;10433:115;10087:468;;;;;:::o;10561:311::-;10638:4;10728:18;10720:6;10717:30;10714:56;;;10750:18;;:::i;:::-;10714:56;10800:4;10792:6;10788:17;10780:25;;10860:4;10854;10850:15;10842:23;;10561:311;;;:::o;10878:117::-;10987:1;10984;10977:12;11018:710;11114:5;11139:81;11155:64;11212:6;11155:64;:::i;:::-;11139:81;:::i;:::-;11130:90;;11240:5;11269:6;11262:5;11255:21;11303:4;11296:5;11292:16;11285:23;;11356:4;11348:6;11344:17;11336:6;11332:30;11385:3;11377:6;11374:15;11371:122;;;11404:79;;:::i;:::-;11371:122;11519:6;11502:220;11536:6;11531:3;11528:15;11502:220;;;11611:3;11640:37;11673:3;11661:10;11640:37;:::i;:::-;11635:3;11628:50;11707:4;11702:3;11698:14;11691:21;;11578:144;11562:4;11557:3;11553:14;11546:21;;11502:220;;;11506:21;11120:608;;11018:710;;;;;:::o;11751:370::-;11822:5;11871:3;11864:4;11856:6;11852:17;11848:27;11838:122;;11879:79;;:::i;:::-;11838:122;11996:6;11983:20;12021:94;12111:3;12103:6;12096:4;12088:6;12084:17;12021:94;:::i;:::-;12012:103;;11828:293;11751:370;;;;:::o;12127:539::-;12211:6;12260:2;12248:9;12239:7;12235:23;12231:32;12228:119;;;12266:79;;:::i;:::-;12228:119;12414:1;12403:9;12399:17;12386:31;12444:18;12436:6;12433:30;12430:117;;;12466:79;;:::i;:::-;12430:117;12571:78;12641:7;12632:6;12621:9;12617:22;12571:78;:::i;:::-;12561:88;;12357:302;12127:539;;;;:::o;12672:307::-;12733:4;12823:18;12815:6;12812:30;12809:56;;;12845:18;;:::i;:::-;12809:56;12883:29;12905:6;12883:29;:::i;:::-;12875:37;;12967:4;12961;12957:15;12949:23;;12672:307;;;:::o;12985:423::-;13062:5;13087:65;13103:48;13144:6;13103:48;:::i;:::-;13087:65;:::i;:::-;13078:74;;13175:6;13168:5;13161:21;13213:4;13206:5;13202:16;13251:3;13242:6;13237:3;13233:16;13230:25;13227:112;;;13258:79;;:::i;:::-;13227:112;13348:54;13395:6;13390:3;13385;13348:54;:::i;:::-;13068:340;12985:423;;;;;:::o;13427:338::-;13482:5;13531:3;13524:4;13516:6;13512:17;13508:27;13498:122;;13539:79;;:::i;:::-;13498:122;13656:6;13643:20;13681:78;13755:3;13747:6;13740:4;13732:6;13728:17;13681:78;:::i;:::-;13672:87;;13488:277;13427:338;;;;:::o;13771:943::-;13866:6;13874;13882;13890;13939:3;13927:9;13918:7;13914:23;13910:33;13907:120;;;13946:79;;:::i;:::-;13907:120;14066:1;14091:53;14136:7;14127:6;14116:9;14112:22;14091:53;:::i;:::-;14081:63;;14037:117;14193:2;14219:53;14264:7;14255:6;14244:9;14240:22;14219:53;:::i;:::-;14209:63;;14164:118;14321:2;14347:53;14392:7;14383:6;14372:9;14368:22;14347:53;:::i;:::-;14337:63;;14292:118;14477:2;14466:9;14462:18;14449:32;14508:18;14500:6;14497:30;14494:117;;;14530:79;;:::i;:::-;14494:117;14635:62;14689:7;14680:6;14669:9;14665:22;14635:62;:::i;:::-;14625:72;;14420:287;13771:943;;;;;;;:::o;14720:474::-;14788:6;14796;14845:2;14833:9;14824:7;14820:23;14816:32;14813:119;;;14851:79;;:::i;:::-;14813:119;14971:1;14996:53;15041:7;15032:6;15021:9;15017:22;14996:53;:::i;:::-;14986:63;;14942:117;15098:2;15124:53;15169:7;15160:6;15149:9;15145:22;15124:53;:::i;:::-;15114:63;;15069:118;14720:474;;;;;:::o;15200:180::-;15248:77;15245:1;15238:88;15345:4;15342:1;15335:15;15369:4;15366:1;15359:15;15386:320;15430:6;15467:1;15461:4;15457:12;15447:22;;15514:1;15508:4;15504:12;15535:18;15525:81;;15591:4;15583:6;15579:17;15569:27;;15525:81;15653:2;15645:6;15642:14;15622:18;15619:38;15616:84;;15672:18;;:::i;:::-;15616:84;15437:269;15386:320;;;:::o;15712:332::-;15833:4;15871:2;15860:9;15856:18;15848:26;;15884:71;15952:1;15941:9;15937:17;15928:6;15884:71;:::i;:::-;15965:72;16033:2;16022:9;16018:18;16009:6;15965:72;:::i;:::-;15712:332;;;;;:::o;16050:137::-;16104:5;16135:6;16129:13;16120:22;;16151:30;16175:5;16151:30;:::i;:::-;16050:137;;;;:::o;16193:345::-;16260:6;16309:2;16297:9;16288:7;16284:23;16280:32;16277:119;;;16315:79;;:::i;:::-;16277:119;16435:1;16460:61;16513:7;16504:6;16493:9;16489:22;16460:61;:::i;:::-;16450:71;;16406:125;16193:345;;;;:::o;16544:141::-;16593:4;16616:3;16608:11;;16639:3;16636:1;16629:14;16673:4;16670:1;16660:18;16652:26;;16544:141;;;:::o;16691:93::-;16728:6;16775:2;16770;16763:5;16759:14;16755:23;16745:33;;16691:93;;;:::o;16790:107::-;16834:8;16884:5;16878:4;16874:16;16853:37;;16790:107;;;;:::o;16903:393::-;16972:6;17022:1;17010:10;17006:18;17045:97;17075:66;17064:9;17045:97;:::i;:::-;17163:39;17193:8;17182:9;17163:39;:::i;:::-;17151:51;;17235:4;17231:9;17224:5;17220:21;17211:30;;17284:4;17274:8;17270:19;17263:5;17260:30;17250:40;;16979:317;;16903:393;;;;;:::o;17302:142::-;17352:9;17385:53;17403:34;17412:24;17430:5;17412:24;:::i;:::-;17403:34;:::i;:::-;17385:53;:::i;:::-;17372:66;;17302:142;;;:::o;17450:75::-;17493:3;17514:5;17507:12;;17450:75;;;:::o;17531:269::-;17641:39;17672:7;17641:39;:::i;:::-;17702:91;17751:41;17775:16;17751:41;:::i;:::-;17743:6;17736:4;17730:11;17702:91;:::i;:::-;17696:4;17689:105;17607:193;17531:269;;;:::o;17806:73::-;17851:3;17806:73;:::o;17885:189::-;17962:32;;:::i;:::-;18003:65;18061:6;18053;18047:4;18003:65;:::i;:::-;17938:136;17885:189;;:::o;18080:186::-;18140:120;18157:3;18150:5;18147:14;18140:120;;;18211:39;18248:1;18241:5;18211:39;:::i;:::-;18184:1;18177:5;18173:13;18164:22;;18140:120;;;18080:186;;:::o;18272:543::-;18373:2;18368:3;18365:11;18362:446;;;18407:38;18439:5;18407:38;:::i;:::-;18491:29;18509:10;18491:29;:::i;:::-;18481:8;18477:44;18674:2;18662:10;18659:18;18656:49;;;18695:8;18680:23;;18656:49;18718:80;18774:22;18792:3;18774:22;:::i;:::-;18764:8;18760:37;18747:11;18718:80;:::i;:::-;18377:431;;18362:446;18272:543;;;:::o;18821:117::-;18875:8;18925:5;18919:4;18915:16;18894:37;;18821:117;;;;:::o;18944:169::-;18988:6;19021:51;19069:1;19065:6;19057:5;19054:1;19050:13;19021:51;:::i;:::-;19017:56;19102:4;19096;19092:15;19082:25;;18995:118;18944:169;;;;:::o;19118:295::-;19194:4;19340:29;19365:3;19359:4;19340:29;:::i;:::-;19332:37;;19402:3;19399:1;19395:11;19389:4;19386:21;19378:29;;19118:295;;;;:::o;19418:1395::-;19535:37;19568:3;19535:37;:::i;:::-;19637:18;19629:6;19626:30;19623:56;;;19659:18;;:::i;:::-;19623:56;19703:38;19735:4;19729:11;19703:38;:::i;:::-;19788:67;19848:6;19840;19834:4;19788:67;:::i;:::-;19882:1;19906:4;19893:17;;19938:2;19930:6;19927:14;19955:1;19950:618;;;;20612:1;20629:6;20626:77;;;20678:9;20673:3;20669:19;20663:26;20654:35;;20626:77;20729:67;20789:6;20782:5;20729:67;:::i;:::-;20723:4;20716:81;20585:222;19920:887;;19950:618;20002:4;19998:9;19990:6;19986:22;20036:37;20068:4;20036:37;:::i;:::-;20095:1;20109:208;20123:7;20120:1;20117:14;20109:208;;;20202:9;20197:3;20193:19;20187:26;20179:6;20172:42;20253:1;20245:6;20241:14;20231:24;;20300:2;20289:9;20285:18;20272:31;;20146:4;20143:1;20139:12;20134:17;;20109:208;;;20345:6;20336:7;20333:19;20330:179;;;20403:9;20398:3;20394:19;20388:26;20446:48;20488:4;20480:6;20476:17;20465:9;20446:48;:::i;:::-;20438:6;20431:64;20353:156;20330:179;20555:1;20551;20543:6;20539:14;20535:22;20529:4;20522:36;19957:611;;;19920:887;;19510:1303;;;19418:1395;;:::o;20819:230::-;20959:34;20955:1;20947:6;20943:14;20936:58;21028:13;21023:2;21015:6;21011:15;21004:38;20819:230;:::o;21055:366::-;21197:3;21218:67;21282:2;21277:3;21218:67;:::i;:::-;21211:74;;21294:93;21383:3;21294:93;:::i;:::-;21412:2;21407:3;21403:12;21396:19;;21055:366;;;:::o;21427:419::-;21593:4;21631:2;21620:9;21616:18;21608:26;;21680:9;21674:4;21670:20;21666:1;21655:9;21651:17;21644:47;21708:131;21834:4;21708:131;:::i;:::-;21700:139;;21427:419;;;:::o;21852:165::-;21992:17;21988:1;21980:6;21976:14;21969:41;21852:165;:::o;22023:366::-;22165:3;22186:67;22250:2;22245:3;22186:67;:::i;:::-;22179:74;;22262:93;22351:3;22262:93;:::i;:::-;22380:2;22375:3;22371:12;22364:19;;22023:366;;;:::o;22395:419::-;22561:4;22599:2;22588:9;22584:18;22576:26;;22648:9;22642:4;22638:20;22634:1;22623:9;22619:17;22612:47;22676:131;22802:4;22676:131;:::i;:::-;22668:139;;22395:419;;;:::o;22820:180::-;22868:77;22865:1;22858:88;22965:4;22962:1;22955:15;22989:4;22986:1;22979:15;23006:233;23045:3;23068:24;23086:5;23068:24;:::i;:::-;23059:33;;23114:66;23107:5;23104:77;23101:103;;23184:18;;:::i;:::-;23101:103;23231:1;23224:5;23220:13;23213:20;;23006:233;;;:::o;23245:143::-;23302:5;23333:6;23327:13;23318:22;;23349:33;23376:5;23349:33;:::i;:::-;23245:143;;;;:::o;23394:351::-;23464:6;23513:2;23501:9;23492:7;23488:23;23484:32;23481:119;;;23519:79;;:::i;:::-;23481:119;23639:1;23664:64;23720:7;23711:6;23700:9;23696:22;23664:64;:::i;:::-;23654:74;;23610:128;23394:351;;;;:::o;23751:232::-;23891:34;23887:1;23879:6;23875:14;23868:58;23960:15;23955:2;23947:6;23943:15;23936:40;23751:232;:::o;23989:366::-;24131:3;24152:67;24216:2;24211:3;24152:67;:::i;:::-;24145:74;;24228:93;24317:3;24228:93;:::i;:::-;24346:2;24341:3;24337:12;24330:19;;23989:366;;;:::o;24361:419::-;24527:4;24565:2;24554:9;24550:18;24542:26;;24614:9;24608:4;24604:20;24600:1;24589:9;24585:17;24578:47;24642:131;24768:4;24642:131;:::i;:::-;24634:139;;24361:419;;;:::o;24786:191::-;24826:3;24845:20;24863:1;24845:20;:::i;:::-;24840:25;;24879:20;24897:1;24879:20;:::i;:::-;24874:25;;24922:1;24919;24915:9;24908:16;;24943:3;24940:1;24937:10;24934:36;;;24950:18;;:::i;:::-;24934:36;24786:191;;;;:::o;24983:231::-;25123:34;25119:1;25111:6;25107:14;25100:58;25192:14;25187:2;25179:6;25175:15;25168:39;24983:231;:::o;25220:366::-;25362:3;25383:67;25447:2;25442:3;25383:67;:::i;:::-;25376:74;;25459:93;25548:3;25459:93;:::i;:::-;25577:2;25572:3;25568:12;25561:19;;25220:366;;;:::o;25592:419::-;25758:4;25796:2;25785:9;25781:18;25773:26;;25845:9;25839:4;25835:20;25831:1;25820:9;25816:17;25809:47;25873:131;25999:4;25873:131;:::i;:::-;25865:139;;25592:419;;;:::o;26017:180::-;26065:77;26062:1;26055:88;26162:4;26159:1;26152:15;26186:4;26183:1;26176:15;26203:174;26343:26;26339:1;26331:6;26327:14;26320:50;26203:174;:::o;26383:366::-;26525:3;26546:67;26610:2;26605:3;26546:67;:::i;:::-;26539:74;;26622:93;26711:3;26622:93;:::i;:::-;26740:2;26735:3;26731:12;26724:19;;26383:366;;;:::o;26755:419::-;26921:4;26959:2;26948:9;26944:18;26936:26;;27008:9;27002:4;26998:20;26994:1;26983:9;26979:17;26972:47;27036:131;27162:4;27036:131;:::i;:::-;27028:139;;26755:419;;;:::o;27180:228::-;27320:34;27316:1;27308:6;27304:14;27297:58;27389:11;27384:2;27376:6;27372:15;27365:36;27180:228;:::o;27414:366::-;27556:3;27577:67;27641:2;27636:3;27577:67;:::i;:::-;27570:74;;27653:93;27742:3;27653:93;:::i;:::-;27771:2;27766:3;27762:12;27755:19;;27414:366;;;:::o;27786:419::-;27952:4;27990:2;27979:9;27975:18;27967:26;;28039:9;28033:4;28029:20;28025:1;28014:9;28010:17;28003:47;28067:131;28193:4;28067:131;:::i;:::-;28059:139;;27786:419;;;:::o;28211:222::-;28351:34;28347:1;28339:6;28335:14;28328:58;28420:5;28415:2;28407:6;28403:15;28396:30;28211:222;:::o;28439:366::-;28581:3;28602:67;28666:2;28661:3;28602:67;:::i;:::-;28595:74;;28678:93;28767:3;28678:93;:::i;:::-;28796:2;28791:3;28787:12;28780:19;;28439:366;;;:::o;28811:419::-;28977:4;29015:2;29004:9;29000:18;28992:26;;29064:9;29058:4;29054:20;29050:1;29039:9;29035:17;29028:47;29092:131;29218:4;29092:131;:::i;:::-;29084:139;;28811:419;;;:::o;29236:226::-;29376:34;29372:1;29364:6;29360:14;29353:58;29445:9;29440:2;29432:6;29428:15;29421:34;29236:226;:::o;29468:366::-;29610:3;29631:67;29695:2;29690:3;29631:67;:::i;:::-;29624:74;;29707:93;29796:3;29707:93;:::i;:::-;29825:2;29820:3;29816:12;29809:19;;29468:366;;;:::o;29840:419::-;30006:4;30044:2;30033:9;30029:18;30021:26;;30093:9;30087:4;30083:20;30079:1;30068:9;30064:17;30057:47;30121:131;30247:4;30121:131;:::i;:::-;30113:139;;29840:419;;;:::o;30265:230::-;30405:34;30401:1;30393:6;30389:14;30382:58;30474:13;30469:2;30461:6;30457:15;30450:38;30265:230;:::o;30501:366::-;30643:3;30664:67;30728:2;30723:3;30664:67;:::i;:::-;30657:74;;30740:93;30829:3;30740:93;:::i;:::-;30858:2;30853:3;30849:12;30842:19;;30501:366;;;:::o;30873:419::-;31039:4;31077:2;31066:9;31062:18;31054:26;;31126:9;31120:4;31116:20;31112:1;31101:9;31097:17;31090:47;31154:131;31280:4;31154:131;:::i;:::-;31146:139;;30873:419;;;:::o;31298:181::-;31438:33;31434:1;31426:6;31422:14;31415:57;31298:181;:::o;31485:366::-;31627:3;31648:67;31712:2;31707:3;31648:67;:::i;:::-;31641:74;;31724:93;31813:3;31724:93;:::i;:::-;31842:2;31837:3;31833:12;31826:19;;31485:366;;;:::o;31857:419::-;32023:4;32061:2;32050:9;32046:18;32038:26;;32110:9;32104:4;32100:20;32096:1;32085:9;32081:17;32074:47;32138:131;32264:4;32138:131;:::i;:::-;32130:139;;31857:419;;;:::o;32282:148::-;32384:11;32421:3;32406:18;;32282:148;;;;:::o;32436:390::-;32542:3;32570:39;32603:5;32570:39;:::i;:::-;32625:89;32707:6;32702:3;32625:89;:::i;:::-;32618:96;;32723:65;32781:6;32776:3;32769:4;32762:5;32758:16;32723:65;:::i;:::-;32813:6;32808:3;32804:16;32797:23;;32546:280;32436:390;;;;:::o;32832:435::-;33012:3;33034:95;33125:3;33116:6;33034:95;:::i;:::-;33027:102;;33146:95;33237:3;33228:6;33146:95;:::i;:::-;33139:102;;33258:3;33251:10;;32832:435;;;;;:::o;33273:225::-;33413:34;33409:1;33401:6;33397:14;33390:58;33482:8;33477:2;33469:6;33465:15;33458:33;33273:225;:::o;33504:366::-;33646:3;33667:67;33731:2;33726:3;33667:67;:::i;:::-;33660:74;;33743:93;33832:3;33743:93;:::i;:::-;33861:2;33856:3;33852:12;33845:19;;33504:366;;;:::o;33876:419::-;34042:4;34080:2;34069:9;34065:18;34057:26;;34129:9;34123:4;34119:20;34115:1;34104:9;34100:17;34093:47;34157:131;34283:4;34157:131;:::i;:::-;34149:139;;33876:419;;;:::o;34301:220::-;34441:34;34437:1;34429:6;34425:14;34418:58;34510:3;34505:2;34497:6;34493:15;34486:28;34301:220;:::o;34527:366::-;34669:3;34690:67;34754:2;34749:3;34690:67;:::i;:::-;34683:74;;34766:93;34855:3;34766:93;:::i;:::-;34884:2;34879:3;34875:12;34868:19;;34527:366;;;:::o;34899:419::-;35065:4;35103:2;35092:9;35088:18;35080:26;;35152:9;35146:4;35142:20;35138:1;35127:9;35123:17;35116:47;35180:131;35306:4;35180:131;:::i;:::-;35172:139;;34899:419;;;:::o;35324:248::-;35464:34;35460:1;35452:6;35448:14;35441:58;35533:31;35528:2;35520:6;35516:15;35509:56;35324:248;:::o;35578:366::-;35720:3;35741:67;35805:2;35800:3;35741:67;:::i;:::-;35734:74;;35817:93;35906:3;35817:93;:::i;:::-;35935:2;35930:3;35926:12;35919:19;;35578:366;;;:::o;35950:419::-;36116:4;36154:2;36143:9;36139:18;36131:26;;36203:9;36197:4;36193:20;36189:1;36178:9;36174:17;36167:47;36231:131;36357:4;36231:131;:::i;:::-;36223:139;;35950:419;;;:::o;36375:182::-;36515:34;36511:1;36503:6;36499:14;36492:58;36375:182;:::o;36563:366::-;36705:3;36726:67;36790:2;36785:3;36726:67;:::i;:::-;36719:74;;36802:93;36891:3;36802:93;:::i;:::-;36920:2;36915:3;36911:12;36904:19;;36563:366;;;:::o;36935:419::-;37101:4;37139:2;37128:9;37124:18;37116:26;;37188:9;37182:4;37178:20;37174:1;37163:9;37159:17;37152:47;37216:131;37342:4;37216:131;:::i;:::-;37208:139;;36935:419;;;:::o;37360:410::-;37400:7;37423:20;37441:1;37423:20;:::i;:::-;37418:25;;37457:20;37475:1;37457:20;:::i;:::-;37452:25;;37512:1;37509;37505:9;37534:30;37552:11;37534:30;:::i;:::-;37523:41;;37713:1;37704:7;37700:15;37697:1;37694:22;37674:1;37667:9;37647:83;37624:139;;37743:18;;:::i;:::-;37624:139;37408:362;37360:410;;;;:::o;37776:180::-;37824:77;37821:1;37814:88;37921:4;37918:1;37911:15;37945:4;37942:1;37935:15;37962:224;38102:34;38098:1;38090:6;38086:14;38079:58;38171:7;38166:2;38158:6;38154:15;38147:32;37962:224;:::o;38192:366::-;38334:3;38355:67;38419:2;38414:3;38355:67;:::i;:::-;38348:74;;38431:93;38520:3;38431:93;:::i;:::-;38549:2;38544:3;38540:12;38533:19;;38192:366;;;:::o;38564:419::-;38730:4;38768:2;38757:9;38753:18;38745:26;;38817:9;38811:4;38807:20;38803:1;38792:9;38788:17;38781:47;38845:131;38971:4;38845:131;:::i;:::-;38837:139;;38564:419;;;:::o;38989:223::-;39129:34;39125:1;39117:6;39113:14;39106:58;39198:6;39193:2;39185:6;39181:15;39174:31;38989:223;:::o;39218:366::-;39360:3;39381:67;39445:2;39440:3;39381:67;:::i;:::-;39374:74;;39457:93;39546:3;39457:93;:::i;:::-;39575:2;39570:3;39566:12;39559:19;;39218:366;;;:::o;39590:419::-;39756:4;39794:2;39783:9;39779:18;39771:26;;39843:9;39837:4;39833:20;39829:1;39818:9;39814:17;39807:47;39871:131;39997:4;39871:131;:::i;:::-;39863:139;;39590:419;;;:::o;40015:237::-;40155:34;40151:1;40143:6;40139:14;40132:58;40224:20;40219:2;40211:6;40207:15;40200:45;40015:237;:::o;40258:366::-;40400:3;40421:67;40485:2;40480:3;40421:67;:::i;:::-;40414:74;;40497:93;40586:3;40497:93;:::i;:::-;40615:2;40610:3;40606:12;40599:19;;40258:366;;;:::o;40630:419::-;40796:4;40834:2;40823:9;40819:18;40811:26;;40883:9;40877:4;40873:20;40869:1;40858:9;40854:17;40847:47;40911:131;41037:4;40911:131;:::i;:::-;40903:139;;40630:419;;;:::o;41055:175::-;41195:27;41191:1;41183:6;41179:14;41172:51;41055:175;:::o;41236:366::-;41378:3;41399:67;41463:2;41458:3;41399:67;:::i;:::-;41392:74;;41475:93;41564:3;41475:93;:::i;:::-;41593:2;41588:3;41584:12;41577:19;;41236:366;;;:::o;41608:419::-;41774:4;41812:2;41801:9;41797:18;41789:26;;41861:9;41855:4;41851:20;41847:1;41836:9;41832:17;41825:47;41889:131;42015:4;41889:131;:::i;:::-;41881:139;;41608:419;;;:::o;42033:182::-;42173:34;42169:1;42161:6;42157:14;42150:58;42033:182;:::o;42221:366::-;42363:3;42384:67;42448:2;42443:3;42384:67;:::i;:::-;42377:74;;42460:93;42549:3;42460:93;:::i;:::-;42578:2;42573:3;42569:12;42562:19;;42221:366;;;:::o;42593:419::-;42759:4;42797:2;42786:9;42782:18;42774:26;;42846:9;42840:4;42836:20;42832:1;42821:9;42817:17;42810:47;42874:131;43000:4;42874:131;:::i;:::-;42866:139;;42593:419;;;:::o;43018:178::-;43158:30;43154:1;43146:6;43142:14;43135:54;43018:178;:::o;43202:366::-;43344:3;43365:67;43429:2;43424:3;43365:67;:::i;:::-;43358:74;;43441:93;43530:3;43441:93;:::i;:::-;43559:2;43554:3;43550:12;43543:19;;43202:366;;;:::o;43574:419::-;43740:4;43778:2;43767:9;43763:18;43755:26;;43827:9;43821:4;43817:20;43813:1;43802:9;43798:17;43791:47;43855:131;43981:4;43855:131;:::i;:::-;43847:139;;43574:419;;;:::o;43999:98::-;44050:6;44084:5;44078:12;44068:22;;43999:98;;;:::o;44103:168::-;44186:11;44220:6;44215:3;44208:19;44260:4;44255:3;44251:14;44236:29;;44103:168;;;;:::o;44277:373::-;44363:3;44391:38;44423:5;44391:38;:::i;:::-;44445:70;44508:6;44503:3;44445:70;:::i;:::-;44438:77;;44524:65;44582:6;44577:3;44570:4;44563:5;44559:16;44524:65;:::i;:::-;44614:29;44636:6;44614:29;:::i;:::-;44609:3;44605:39;44598:46;;44367:283;44277:373;;;;:::o;44656:640::-;44851:4;44889:3;44878:9;44874:19;44866:27;;44903:71;44971:1;44960:9;44956:17;44947:6;44903:71;:::i;:::-;44984:72;45052:2;45041:9;45037:18;45028:6;44984:72;:::i;:::-;45066;45134:2;45123:9;45119:18;45110:6;45066:72;:::i;:::-;45185:9;45179:4;45175:20;45170:2;45159:9;45155:18;45148:48;45213:76;45284:4;45275:6;45213:76;:::i;:::-;45205:84;;44656:640;;;;;;;:::o;45302:141::-;45358:5;45389:6;45383:13;45374:22;;45405:32;45431:5;45405:32;:::i;:::-;45302:141;;;;:::o;45449:349::-;45518:6;45567:2;45555:9;45546:7;45542:23;45538:32;45535:119;;;45573:79;;:::i;:::-;45535:119;45693:1;45718:63;45773:7;45764:6;45753:9;45749:22;45718:63;:::i;:::-;45708:73;;45664:127;45449:349;;;;:::o;45804:240::-;45944:34;45940:1;45932:6;45928:14;45921:58;46013:23;46008:2;46000:6;45996:15;45989:48;45804:240;:::o;46050:366::-;46192:3;46213:67;46277:2;46272:3;46213:67;:::i;:::-;46206:74;;46289:93;46378:3;46289:93;:::i;:::-;46407:2;46402:3;46398:12;46391:19;;46050:366;;;:::o;46422:419::-;46588:4;46626:2;46615:9;46611:18;46603:26;;46675:9;46669:4;46665:20;46661:1;46650:9;46646:17;46639:47;46703:131;46829:4;46703:131;:::i;:::-;46695:139;;46422:419;;;:::o;46847:194::-;46887:4;46907:20;46925:1;46907:20;:::i;:::-;46902:25;;46941:20;46959:1;46941:20;:::i;:::-;46936:25;;46985:1;46982;46978:9;46970:17;;47009:1;47003:4;47000:11;46997:37;;;47014:18;;:::i;:::-;46997:37;46847:194;;;;:::o;47047:180::-;47095:77;47092:1;47085:88;47192:4;47189:1;47182:15;47216:4;47213:1;47206:15

Swarm Source

ipfs://a9be460dd2aeee2582de153d35c38c0765f1f0a287b2d5f8c68cbb2b24735c4e
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.