Skip to content

Commit

Permalink
Add ABI coder function to compute default values (#1101).
Browse files Browse the repository at this point in the history
  • Loading branch information
ricmoo committed Nov 23, 2020
1 parent 7f775f7 commit a8e3380
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 0 deletions.
6 changes: 6 additions & 0 deletions packages/abi/src.ts/abi-coder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ export class AbiCoder {
return new Writer(this._getWordSize());
}

getDefaultValue(types: Array<string | ParamType>): Result {
const coders: Array<Coder> = types.map((type) => this._getCoder(ParamType.from(type)));
const coder = new TupleCoder(coders, "_");
return coder.defaultValue();
}

encode(types: Array<string | ParamType>, values: Array<any>): string {
if (types.length !== values.length) {
logger.throwError("types/values length mismatch", Logger.errors.INVALID_ARGUMENT, {
Expand Down
2 changes: 2 additions & 0 deletions packages/abi/src.ts/coders/abstract-coder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ export abstract class Coder {

abstract encode(writer: Writer, value: any): number;
abstract decode(reader: Reader): any;

abstract defaultValue(): any;
}

export class Writer {
Expand Down
4 changes: 4 additions & 0 deletions packages/abi/src.ts/coders/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export class AddressCoder extends Coder {
super("address", "address", localName, false);
}

defaultValue(): string {
return "0x0000000000000000000000000000000000000000";
}

encode(writer: Writer, value: string): number {
try {
getAddress(value);
Expand Down
4 changes: 4 additions & 0 deletions packages/abi/src.ts/coders/anonymous.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export class AnonymousCoder extends Coder {
this.coder = coder;
}

defaultValue(): any {
return this.coder.defaultValue();
}

encode(writer: Writer, value: any): number {
return this.coder.encode(writer, value);
}
Expand Down
11 changes: 11 additions & 0 deletions packages/abi/src.ts/coders/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,17 @@ export class ArrayCoder extends Coder {
this.length = length;
}

defaultValue(): Array<any> {
// Verifies the child coder is valid (even if the array is dynamic or 0-length)
const defaultChild = this.coder.defaultValue();

const result: Array<any> = [];
for (let i = 0; i < this.length; i++) {
result.push(defaultChild);
}
return result;
}

encode(writer: Writer, value: Array<any>): number {
if (!Array.isArray(value)) {
this._throwError("expected array value", value);
Expand Down
4 changes: 4 additions & 0 deletions packages/abi/src.ts/coders/boolean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export class BooleanCoder extends Coder {
super("bool", "bool", localName, false);
}

defaultValue(): boolean {
return false;
}

encode(writer: Writer, value: boolean): number {
return writer.writeValue(value ? 1: 0);
}
Expand Down
4 changes: 4 additions & 0 deletions packages/abi/src.ts/coders/bytes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export class DynamicBytesCoder extends Coder {
super(type, type, localName, true);
}

defaultValue(): string {
return "0x";
}

encode(writer: Writer, value: any): number {
value = arrayify(value);
let length = writer.writeValue(value.length);
Expand Down
4 changes: 4 additions & 0 deletions packages/abi/src.ts/coders/fixed-bytes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export class FixedBytesCoder extends Coder {
this.size = size;
}

defaultValue(): string {
return ("0x0000000000000000000000000000000000000000000000000000000000000000").substring(0, 2 + this.size * 2);
}

encode(writer: Writer, value: BytesLike): number {
let data = arrayify(value);
if (data.length !== this.size) { this._throwError("incorrect data length", value); }
Expand Down
4 changes: 4 additions & 0 deletions packages/abi/src.ts/coders/null.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export class NullCoder extends Coder {
super("null", "", localName, false);
}

defaultValue(): null {
return null;
}

encode(writer: Writer, value: any): number {
if (value != null) { this._throwError("not null", value); }
return writer.writeBytes([ ]);
Expand Down
4 changes: 4 additions & 0 deletions packages/abi/src.ts/coders/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export class NumberCoder extends Coder {
this.signed = signed;
}

defaultValue(): number {
return 0;
}

encode(writer: Writer, value: BigNumberish): number {
let v = BigNumber.from(value);

Expand Down
4 changes: 4 additions & 0 deletions packages/abi/src.ts/coders/string.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export class StringCoder extends DynamicBytesCoder {
super("string", localName);
}

defaultValue(): string {
return "";
}

encode(writer: Writer, value: any): number {
return super.encode(writer, toUtf8Bytes(value));
}
Expand Down
31 changes: 31 additions & 0 deletions packages/abi/src.ts/coders/tuple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,37 @@ export class TupleCoder extends Coder {
this.coders = coders;
}

defaultValue(): any {
const values: any = [ ];
this.coders.forEach((coder) => {
values.push(coder.defaultValue());
});

// We only output named properties for uniquely named coders
const uniqueNames = this.coders.reduce((accum, coder) => {
const name = coder.localName;
if (name) {
if (!accum[name]) { accum[name] = 0; }
accum[name]++;
}
return accum;
}, <{ [ name: string ]: number }>{ });

// Add named values
this.coders.forEach((coder: Coder, index: number) => {
let name = coder.localName;
if (!name || uniqueNames[name] !== 1) { return; }

if (name === "length") { name = "_length"; }

if (values[name] != null) { return; }

values[name] = values[index];
});

return Object.freeze(values);
}

encode(writer: Writer, value: Array<any> | { [ name: string ]: any }): number {
return pack(writer, this.coders, value);
}
Expand Down

0 comments on commit a8e3380

Please sign in to comment.