Converts a lowercase hex Ethereum address to EIP-55 checksum address
| 142 | |
| 143 | // Converts a lowercase hex Ethereum address to EIP-55 checksum address |
| 144 | inline std::string toChecksumAddress(const std::string &address) { |
| 145 | // Remove 0x prefix if present and convert to lowercase |
| 146 | std::string stripAddress = address; |
| 147 | if (stripAddress.rfind("0x", 0) == 0 || stripAddress.rfind("0X", 0) == 0) { |
| 148 | stripAddress = stripAddress.substr(2); |
| 149 | } |
| 150 | std::transform(stripAddress.begin(), stripAddress.end(), stripAddress.begin(), |
| 151 | ::tolower); |
| 152 | |
| 153 | // Validate address: must be 40 hex chars and all hex digits |
| 154 | if (stripAddress.size() != 40 || |
| 155 | !std::all_of(stripAddress.begin(), stripAddress.end(), [](char c) { |
| 156 | return std::isxdigit(static_cast<unsigned char>(c)); |
| 157 | })) { |
| 158 | throw std::invalid_argument("Invalid Ethereum address: " + address); |
| 159 | } |
| 160 | |
| 161 | // Keccak-256 hash of the address (no 0x prefix) |
| 162 | std::vector<uint8_t> addr_bytes(stripAddress.begin(), stripAddress.end()); |
| 163 | Keccak keccak(Keccak::Keccak256); |
| 164 | std::string hash_hex = keccak(addr_bytes.data(), addr_bytes.size()); |
| 165 | |
| 166 | // Build the checksum address |
| 167 | std::string checksumAddress = "0x"; |
| 168 | for (size_t i = 0; i < stripAddress.size(); ++i) { |
| 169 | int hash_nibble = std::stoi(hash_hex.substr(i, 1), nullptr, 16); |
| 170 | if (hash_nibble >= 8) { |
| 171 | checksumAddress += std::toupper(stripAddress[i]); |
| 172 | } else { |
| 173 | checksumAddress += stripAddress[i]; |
| 174 | } |
| 175 | } |
| 176 | return checksumAddress; |
| 177 | } |
| 178 | |
| 179 | } // namespace quip |
no outgoing calls
no test coverage detected