diff --git a/src/v3/core/address.js b/src/v3/core/address.js
index 009849c..9069df1 100644
--- a/src/v3/core/address.js
+++ b/src/v3/core/address.js
@@ -1,5 +1,7 @@
// @flow
+import stringify from "json-stable-stringify";
+
export interface AddressModule
{
/**
* Assert at runtime that the provided address is actually a valid
@@ -89,7 +91,31 @@ export type Options = {|
export function makeAddressModule(options: Options): AddressModule {
type Address = string; // for readability and interface consistency
- const _ = options;
+ const {name, nonce} = options;
+ const otherNonces = new Map(options.otherNonces || new Map());
+
+ const separator = "\0";
+ if (nonce.indexOf(separator) !== -1) {
+ throw new Error(`invalid nonce (contains NUL): ${stringify(nonce)}`);
+ }
+
+ const nonceWithSeparator = nonce + separator;
+ const otherNoncesWithSeparators = new Map();
+ for (const [otherNonce, otherName] of otherNonces.entries()) {
+ if (otherNonce === nonce) {
+ throw new Error(
+ `primary nonce listed as otherNonce: ${stringify(nonce)}`
+ );
+ }
+ if (otherNonce.indexOf(separator) !== -1) {
+ throw new Error(
+ `invalid otherNonce (contains NUL): ${stringify(otherNonce)}`
+ );
+ }
+ otherNoncesWithSeparators.set(otherNonce + separator, otherName);
+ }
+
+ const _ = {name, nonceWithSeparator};
function assertValid(address: Address, what?: string): void {
const _ = {address, what};
diff --git a/src/v3/core/address.test.js b/src/v3/core/address.test.js
index 6feb667..7d194ce 100644
--- a/src/v3/core/address.test.js
+++ b/src/v3/core/address.test.js
@@ -28,6 +28,29 @@ describe("core/address", () => {
it("makes address modules using all the options", () => {
makeModules();
});
+ it("rejects a module whose nonce contains NUL", () => {
+ expect(() => {
+ makeAddressModule({name: "BadAddress", nonce: "n\0o"});
+ }).toThrow("invalid nonce (contains NUL):");
+ });
+ it("rejects a module with `otherNonces` containing NUL", () => {
+ expect(() => {
+ makeAddressModule({
+ name: "GoodAddress",
+ nonce: "G",
+ otherNonces: new Map().set("n\0o", "BadAddress"),
+ });
+ }).toThrow("invalid otherNonce (contains NUL):");
+ });
+ it("rejects a module with `nonce` in `otherNonces`", () => {
+ expect(() => {
+ makeAddressModule({
+ name: "GoodAddress",
+ nonce: "G",
+ otherNonces: new Map().set("G", "WatAddress"),
+ });
+ }).toThrow("primary nonce listed as otherNonce");
+ });
it("returns an object with read-only properties", () => {
const {FooAddress} = makeModules();
expect(() => {