-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix EIP-712 type aliases for uint and int (#4541).
- Loading branch information
Showing
2 changed files
with
102 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,12 +124,12 @@ const domainChecks: Record<string, (value: any) => any> = { | |
function getBaseEncoder(type: string): null | ((value: any) => string) { | ||
// intXX and uintXX | ||
{ | ||
const match = type.match(/^(u?)int(\d*)$/); | ||
const match = type.match(/^(u?)int(\d+)$/); | ||
if (match) { | ||
const signed = (match[1] === ""); | ||
|
||
const width = parseInt(match[2] || "256"); | ||
assertArgument(width % 8 === 0 && width !== 0 && width <= 256 && (match[2] == null || match[2] === String(width)), "invalid numeric width", "type", type); | ||
const width = parseInt(match[2]); | ||
assertArgument(width % 8 === 0 && width !== 0 && width <= 256 && match[2] === String(width), "invalid numeric width", "type", type); | ||
|
||
const boundsUpper = mask(BN_MAX_UINT256, signed ? (width - 1): width); | ||
const boundsLower = signed ? ((boundsUpper + BN_1) * BN__1): BN_0; | ||
|
@@ -220,8 +220,7 @@ export class TypedDataEncoder { | |
* do not violate the [[link-eip-712]] structural constraints as | ||
* well as computes the [[primaryType]]. | ||
*/ | ||
constructor(types: Record<string, Array<TypedDataField>>) { | ||
this.#types = JSON.stringify(types); | ||
constructor(_types: Record<string, Array<TypedDataField>>) { | ||
this.#fullTypes = new Map(); | ||
this.#encoderCache = new Map(); | ||
|
||
|
@@ -234,30 +233,39 @@ export class TypedDataEncoder { | |
// Link all subtypes within a given struct | ||
const subtypes: Map<string, Set<string>> = new Map(); | ||
|
||
Object.keys(types).forEach((type) => { | ||
const types: Record<string, Array<TypedDataField>> = { }; | ||
Object.keys(_types).forEach((type) => { | ||
// Normalize int/uint unless they are a complex type themselves | ||
types[type] = _types[type].map(({ name, type }) => { | ||
if (type === "int" && !_types["int"]) { type = "int256"; } | ||
if (type === "uint" && !_types["uint"]) { type = "uint256"; } | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
ricmoo
Author
Member
|
||
return { name, type }; | ||
}); | ||
|
||
links.set(type, new Set()); | ||
parents.set(type, [ ]); | ||
subtypes.set(type, new Set()); | ||
}); | ||
this.#types = JSON.stringify(types); | ||
|
||
for (const name in types) { | ||
const uniqueNames: Set<string> = new Set(); | ||
|
||
for (const field of types[name]) { | ||
|
||
// Check each field has a unique name | ||
assertArgument(!uniqueNames.has(field.name), `duplicate variable name ${ JSON.stringify(field.name) } in ${ JSON.stringify(name) }`, "types", types); | ||
assertArgument(!uniqueNames.has(field.name), `duplicate variable name ${ JSON.stringify(field.name) } in ${ JSON.stringify(name) }`, "types", _types); | ||
uniqueNames.add(field.name); | ||
|
||
// Get the base type (drop any array specifiers) | ||
const baseType = (<any>(field.type.match(/^([^\x5b]*)(\x5b|$)/)))[1] || null; | ||
assertArgument(baseType !== name, `circular type reference to ${ JSON.stringify(baseType) }`, "types", types); | ||
assertArgument(baseType !== name, `circular type reference to ${ JSON.stringify(baseType) }`, "types", _types); | ||
|
||
// Is this a base encoding type? | ||
const encoder = getBaseEncoder(baseType); | ||
if (encoder) { continue; } | ||
|
||
assertArgument(parents.has(baseType), `unknown type ${ JSON.stringify(baseType) }`, "types", types); | ||
assertArgument(parents.has(baseType), `unknown type ${ JSON.stringify(baseType) }`, "types", _types); | ||
|
||
// Add linkage | ||
(parents.get(baseType) as Array<string>).push(name); | ||
|
@@ -267,14 +275,14 @@ export class TypedDataEncoder { | |
|
||
// Deduce the primary type | ||
const primaryTypes = Array.from(parents.keys()).filter((n) => ((parents.get(n) as Array<string>).length === 0)); | ||
assertArgument(primaryTypes.length !== 0, "missing primary type", "types", types); | ||
assertArgument(primaryTypes.length === 1, `ambiguous primary types or unused types: ${ primaryTypes.map((t) => (JSON.stringify(t))).join(", ") }`, "types", types); | ||
assertArgument(primaryTypes.length !== 0, "missing primary type", "types", _types); | ||
assertArgument(primaryTypes.length === 1, `ambiguous primary types or unused types: ${ primaryTypes.map((t) => (JSON.stringify(t))).join(", ") }`, "types", _types); | ||
|
||
defineProperties<TypedDataEncoder>(this, { primaryType: primaryTypes[0] }); | ||
|
||
// Check for circular type references | ||
function checkCircular(type: string, found: Set<string>) { | ||
assertArgument(!found.has(type), `circular type reference to ${ JSON.stringify(type) }`, "types", types); | ||
assertArgument(!found.has(type), `circular type reference to ${ JSON.stringify(type) }`, "types", _types); | ||
|
||
found.add(type); | ||
|
||
|
@ricmoo What is
_types["int"]
for? The key for_types
is for signature type not data type?