This commit is contained in:
parent
1d6b04c4f7
commit
2a4e2c1c85
8 changed files with 1381 additions and 41 deletions
|
|
@ -41,10 +41,18 @@ int main() {
|
|||
"eurc: €570.43 as 6-decimal base units, full 32-byte word");
|
||||
Check(ParseEthCallUint(R"({"result":"0xFF"})") == 255,
|
||||
"eurc: uppercase hex accepted");
|
||||
// 2^63 does not fit; the decoder must saturate, never wrap to negative.
|
||||
Check(ParseEthCallUint(R"({"result":"0x8000000000000000"})")
|
||||
== std::numeric_limits<std::int64_t>::max(),
|
||||
"eurc: overflow saturates");
|
||||
// 2^63 does not fit. It must not wrap to negative, and it must not
|
||||
// saturate to INT64_MAX either: a saturated maximum satisfies the covering
|
||||
// comparison in CheckPaid, so a node answering 0xffff…ff would mark any
|
||||
// order paid. int64 base units is already past EURC's entire supply, so an
|
||||
// unrepresentable balance is a broken or lying node — "unknown", which
|
||||
// neither settles nor lapses.
|
||||
Check(!ParseEthCallUint(R"({"result":"0x8000000000000000"})").has_value(),
|
||||
"eurc: an unrepresentable balance is unknown, not a covering maximum");
|
||||
Check(!ParseEthCallUint(
|
||||
R"({"result":"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"})")
|
||||
.has_value(),
|
||||
"eurc: a lying node's 2^256-1 does not read as paid");
|
||||
Check(!ParseEthCallUint(
|
||||
R"({"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"x"}})")
|
||||
.has_value(),
|
||||
|
|
@ -85,6 +93,47 @@ int main() {
|
|||
Check(!Server::ParseEurcChains("garbage").has_value(),
|
||||
"eurc: malformed chains file rejected");
|
||||
|
||||
// Two chains with one name would share a connection-map slot, so the
|
||||
// second's requests would go to the first's host and one chain would never
|
||||
// be watched at all.
|
||||
Check(!Server::ParseEurcChains(R"({"chains":[
|
||||
{"name":"base","rpc":"https://a.example",
|
||||
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"},
|
||||
{"name":"base","rpc":"https://b.example",
|
||||
"contract":"0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c"}]})").has_value(),
|
||||
"eurc: duplicate chain names reject the whole file");
|
||||
|
||||
// 18 decimals is legal ERC-20 but not representable here: cents × 10^16
|
||||
// overflows int64 above €9.22, and the overflow answers "unknown", which
|
||||
// neither settles nor lapses an order.
|
||||
Check(!Server::ParseEurcChains(R"({"chains":[
|
||||
{"name":"base","rpc":"https://a.example","decimals":18,
|
||||
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})").has_value(),
|
||||
"eurc: decimals beyond what the arithmetic carries is refused");
|
||||
|
||||
// block_tag reaches the eth_call params array. A quote in it closed the
|
||||
// JSON string and appended another param; a typo silenced the chain.
|
||||
Check(!Server::ParseEurcChains(R"({"chains":[
|
||||
{"name":"base","rpc":"https://a.example","block_tag":"latest\",\"0xdead",
|
||||
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})").has_value(),
|
||||
"eurc: a block_tag that injects JSON is refused");
|
||||
Check(!Server::ParseEurcChains(R"({"chains":[
|
||||
{"name":"base","rpc":"https://a.example","block_tag":"finalised",
|
||||
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})").has_value(),
|
||||
"eurc: a misspelled block_tag is refused, not silently never-settling");
|
||||
Check(!Server::ParseEurcChains(R"({"chains":[
|
||||
{"name":"base","rpc":"https://a.example","block_tag":"",
|
||||
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})").has_value(),
|
||||
"eurc: an empty block_tag is refused");
|
||||
{
|
||||
// A specific block number stays legitimate.
|
||||
const auto ok = Server::ParseEurcChains(R"({"chains":[
|
||||
{"name":"base","rpc":"https://a.example","block_tag":"0x1b4",
|
||||
"contract":"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"}]})");
|
||||
Check(ok.has_value() && (*ok)[0].blockTag == "0x1b4",
|
||||
"eurc: a hex block number is still accepted");
|
||||
}
|
||||
|
||||
if (failures != 0) {
|
||||
std::println(std::cerr, "{} check(s) failed", failures);
|
||||
return 1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue