Skip to content

enforce address normalization at compile-time #811

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/wallet/core/src/envelope.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Config, Payload, Signature } from '@0xsequence/wallet-primitives'
import { Address, Hex } from 'ox'
import { Address, Config, Payload, Signature } from '@0xsequence/wallet-primitives'
import { Hex } from 'ox'

export type Envelope<T extends Payload.Payload> = {
readonly wallet: Address.Address
readonly wallet: Address.Checksummed
readonly chainId: bigint
readonly configuration: Config.Config
readonly payload: T
}

export type Signature = {
address: Address.Address
address: Address.Checksummed
signature: Signature.SignatureOfSignerLeaf
}

Expand Down
78 changes: 44 additions & 34 deletions packages/wallet/core/src/preconditions/codec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Address } from 'ox'
import { Address } from '@0xsequence/wallet-primitives'
import {
Precondition,
NativeBalancePrecondition,
Expand Down Expand Up @@ -41,52 +41,52 @@ export function decodePrecondition(p: IntentPrecondition): Precondition | undefi
switch (p.type) {
case 'native-balance':
precondition = new NativeBalancePrecondition(
Address.from(data.address),
Address.checksum(data.address),
data.min ? BigInt(data.min) : undefined,
data.max ? BigInt(data.max) : undefined,
)
break

case 'erc20-balance':
precondition = new Erc20BalancePrecondition(
Address.from(data.address),
Address.from(data.token),
Address.checksum(data.address),
Address.checksum(data.token),
data.min ? BigInt(data.min) : undefined,
data.max ? BigInt(data.max) : undefined,
)
break

case 'erc20-approval':
precondition = new Erc20ApprovalPrecondition(
Address.from(data.address),
Address.from(data.token),
Address.from(data.operator),
Address.checksum(data.address),
Address.checksum(data.token),
Address.checksum(data.operator),
BigInt(data.min),
)
break

case 'erc721-ownership':
precondition = new Erc721OwnershipPrecondition(
Address.from(data.address),
Address.from(data.token),
Address.checksum(data.address),
Address.checksum(data.token),
BigInt(data.tokenId),
data.owned,
)
break

case 'erc721-approval':
precondition = new Erc721ApprovalPrecondition(
Address.from(data.address),
Address.from(data.token),
Address.checksum(data.address),
Address.checksum(data.token),
BigInt(data.tokenId),
Address.from(data.operator),
Address.checksum(data.operator),
)
break

case 'erc1155-balance':
precondition = new Erc1155BalancePrecondition(
Address.from(data.address),
Address.from(data.token),
Address.checksum(data.address),
Address.checksum(data.token),
BigInt(data.tokenId),
data.min ? BigInt(data.min) : undefined,
data.max ? BigInt(data.max) : undefined,
Expand All @@ -95,10 +95,10 @@ export function decodePrecondition(p: IntentPrecondition): Precondition | undefi

case 'erc1155-approval':
precondition = new Erc1155ApprovalPrecondition(
Address.from(data.address),
Address.from(data.token),
Address.checksum(data.address),
Address.checksum(data.token),
BigInt(data.tokenId),
Address.from(data.operator),
Address.checksum(data.operator),
BigInt(data.min),
)
break
Expand All @@ -120,58 +120,68 @@ export function decodePrecondition(p: IntentPrecondition): Precondition | undefi
}
}

type PreconditionData = {
address: Address.Checksummed
token: Address.Checksummed
operator: Address.Checksummed
min: string
max: string
tokenId: string
owned: boolean
}

export function encodePrecondition(p: Precondition): string {
const data: any = {}
const data: Partial<PreconditionData> = {}

switch (p.type()) {
case 'native-balance': {
const native = p as NativeBalancePrecondition
data.address = native.address.toString()
data.address = native.address
if (native.min !== undefined) data.min = native.min.toString()
if (native.max !== undefined) data.max = native.max.toString()
break
}

case 'erc20-balance': {
const erc20 = p as Erc20BalancePrecondition
data.address = erc20.address.toString()
data.token = erc20.token.toString()
data.address = erc20.address
data.token = erc20.token
if (erc20.min !== undefined) data.min = erc20.min.toString()
if (erc20.max !== undefined) data.max = erc20.max.toString()
break
}

case 'erc20-approval': {
const erc20 = p as Erc20ApprovalPrecondition
data.address = erc20.address.toString()
data.token = erc20.token.toString()
data.operator = erc20.operator.toString()
data.address = erc20.address
data.token = erc20.token
data.operator = erc20.operator
data.min = erc20.min.toString()
break
}

case 'erc721-ownership': {
const erc721 = p as Erc721OwnershipPrecondition
data.address = erc721.address.toString()
data.token = erc721.token.toString()
data.address = erc721.address
data.token = erc721.token
data.tokenId = erc721.tokenId.toString()
if (erc721.owned !== undefined) data.owned = erc721.owned
break
}

case 'erc721-approval': {
const erc721 = p as Erc721ApprovalPrecondition
data.address = erc721.address.toString()
data.token = erc721.token.toString()
data.address = erc721.address
data.token = erc721.token
data.tokenId = erc721.tokenId.toString()
data.operator = erc721.operator.toString()
data.operator = erc721.operator
break
}

case 'erc1155-balance': {
const erc1155 = p as Erc1155BalancePrecondition
data.address = erc1155.address.toString()
data.token = erc1155.token.toString()
data.address = erc1155.address
data.token = erc1155.token
data.tokenId = erc1155.tokenId.toString()
if (erc1155.min !== undefined) data.min = erc1155.min.toString()
if (erc1155.max !== undefined) data.max = erc1155.max.toString()
Expand All @@ -180,10 +190,10 @@ export function encodePrecondition(p: Precondition): string {

case 'erc1155-approval': {
const erc1155 = p as Erc1155ApprovalPrecondition
data.address = erc1155.address.toString()
data.token = erc1155.token.toString()
data.address = erc1155.address
data.token = erc1155.token
data.tokenId = erc1155.tokenId.toString()
data.operator = erc1155.operator.toString()
data.operator = erc1155.operator
data.min = erc1155.min.toString()
break
}
Expand Down
34 changes: 17 additions & 17 deletions packages/wallet/core/src/preconditions/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Address } from 'ox'
import { Address } from '@0xsequence/wallet-primitives'

export interface Precondition {
type(): string
Expand All @@ -7,7 +7,7 @@ export interface Precondition {

export class NativeBalancePrecondition implements Precondition {
constructor(
public readonly address: Address.Address,
public readonly address: Address.Checksummed,
public readonly min?: bigint,
public readonly max?: bigint,
) {}
Expand All @@ -29,8 +29,8 @@ export class NativeBalancePrecondition implements Precondition {

export class Erc20BalancePrecondition implements Precondition {
constructor(
public readonly address: Address.Address,
public readonly token: Address.Address,
public readonly address: Address.Checksummed,
public readonly token: Address.Checksummed,
public readonly min?: bigint,
public readonly max?: bigint,
) {}
Expand All @@ -55,9 +55,9 @@ export class Erc20BalancePrecondition implements Precondition {

export class Erc20ApprovalPrecondition implements Precondition {
constructor(
public readonly address: Address.Address,
public readonly token: Address.Address,
public readonly operator: Address.Address,
public readonly address: Address.Checksummed,
public readonly token: Address.Checksummed,
public readonly operator: Address.Checksummed,
public readonly min: bigint,
) {}

Expand All @@ -84,8 +84,8 @@ export class Erc20ApprovalPrecondition implements Precondition {

export class Erc721OwnershipPrecondition implements Precondition {
constructor(
public readonly address: Address.Address,
public readonly token: Address.Address,
public readonly address: Address.Checksummed,
public readonly token: Address.Checksummed,
public readonly tokenId: bigint,
public readonly owned?: boolean,
) {}
Expand All @@ -110,10 +110,10 @@ export class Erc721OwnershipPrecondition implements Precondition {

export class Erc721ApprovalPrecondition implements Precondition {
constructor(
public readonly address: Address.Address,
public readonly token: Address.Address,
public readonly address: Address.Checksummed,
public readonly token: Address.Checksummed,
public readonly tokenId: bigint,
public readonly operator: Address.Address,
public readonly operator: Address.Checksummed,
) {}

type(): string {
Expand All @@ -139,8 +139,8 @@ export class Erc721ApprovalPrecondition implements Precondition {

export class Erc1155BalancePrecondition implements Precondition {
constructor(
public readonly address: Address.Address,
public readonly token: Address.Address,
public readonly address: Address.Checksummed,
public readonly token: Address.Checksummed,
public readonly tokenId: bigint,
public readonly min?: bigint,
public readonly max?: bigint,
Expand Down Expand Up @@ -169,10 +169,10 @@ export class Erc1155BalancePrecondition implements Precondition {

export class Erc1155ApprovalPrecondition implements Precondition {
constructor(
public readonly address: Address.Address,
public readonly token: Address.Address,
public readonly address: Address.Checksummed,
public readonly token: Address.Checksummed,
public readonly tokenId: bigint,
public readonly operator: Address.Address,
public readonly operator: Address.Checksummed,
public readonly min: bigint,
) {}

Expand Down
10 changes: 5 additions & 5 deletions packages/wallet/core/src/relayer/bundler.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Payload } from '@0xsequence/wallet-primitives'
import { Address, Hex } from 'ox'
import { Address, Payload } from '@0xsequence/wallet-primitives'
import { Hex } from 'ox'
import { UserOperation } from 'ox/erc4337'
import { OperationStatus } from './relayer.js'

Expand All @@ -9,13 +9,13 @@ export interface Bundler {
id: string

estimateLimits(
wallet: Address.Address,
wallet: Address.Checksummed,
payload: Payload.Calls4337_07,
): Promise<{ speed?: 'slow' | 'standard' | 'fast'; payload: Payload.Calls4337_07 }[]>
relay(entrypoint: Address.Address, userOperation: UserOperation.RpcV07): Promise<{ opHash: Hex.Hex }>
relay(entrypoint: Address.Checksummed, userOperation: UserOperation.RpcV07): Promise<{ opHash: Hex.Hex }>
status(opHash: Hex.Hex, chainId: bigint): Promise<OperationStatus>

isAvailable(entrypoint: Address.Address, chainId: bigint): Promise<boolean>
isAvailable(entrypoint: Address.Checksummed, chainId: bigint): Promise<boolean>
}

export function isBundler(relayer: any): relayer is Bundler {
Expand Down
12 changes: 6 additions & 6 deletions packages/wallet/core/src/relayer/bundlers/pimlico.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Payload } from '@0xsequence/wallet-primitives'
import { Address, Payload } from '@0xsequence/wallet-primitives'
import { Bundler } from '../bundler.js'
import { Provider, Hex, Address, RpcTransport } from 'ox'
import { Provider, Hex, RpcTransport } from 'ox'
import { UserOperation } from 'ox/erc4337'
import { OperationStatus } from '../relayer.js'

Expand Down Expand Up @@ -28,10 +28,10 @@ export class PimlicoBundler implements Bundler {
this.bundlerRpcUrl = bundlerRpcUrl
}

async isAvailable(entrypoint: Address.Address, chainId: bigint): Promise<boolean> {
async isAvailable(entrypoint: Address.Checksummed, chainId: bigint): Promise<boolean> {
const [bundlerChainId, supportedEntryPoints] = await Promise.all([
this.bundlerRpc<string>('eth_chainId', []),
this.bundlerRpc<Address.Address[]>('eth_supportedEntryPoints', []),
this.bundlerRpc<Address.Checksummed[]>('eth_supportedEntryPoints', []),
])

if (chainId !== BigInt(bundlerChainId)) {
Expand All @@ -41,13 +41,13 @@ export class PimlicoBundler implements Bundler {
return supportedEntryPoints.some((ep) => Address.isEqual(ep, entrypoint))
}

async relay(entrypoint: Address.Address, userOperation: UserOperation.RpcV07): Promise<{ opHash: Hex.Hex }> {
async relay(entrypoint: Address.Checksummed, userOperation: UserOperation.RpcV07): Promise<{ opHash: Hex.Hex }> {
const status = await this.bundlerRpc<Hex.Hex>('eth_sendUserOperation', [userOperation, entrypoint])
return { opHash: status }
}

async estimateLimits(
wallet: Address.Address,
wallet: Address.Checksummed,
payload: Payload.Calls4337_07,
): Promise<
{
Expand Down
12 changes: 6 additions & 6 deletions packages/wallet/core/src/relayer/relayer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Payload, Precondition } from '@0xsequence/wallet-primitives'
import { Address, Hex } from 'ox'
import { Address, Payload, Precondition } from '@0xsequence/wallet-primitives'
import { Hex } from 'ox'
import { FeeToken, GetMetaTxnReceiptReturn } from './standard/rpc/index.js'

export interface FeeOption {
token: FeeToken
to: string
to: Address.Checksummed
value: string
gasLimit: number
}
Expand Down Expand Up @@ -61,15 +61,15 @@ export interface Relayer {
type: string
id: string

isAvailable(wallet: Address.Address, chainId: bigint): Promise<boolean>
isAvailable(wallet: Address.Checksummed, chainId: bigint): Promise<boolean>

feeOptions(
wallet: Address.Address,
wallet: Address.Checksummed,
chainId: bigint,
calls: Payload.Call[],
): Promise<{ options: FeeOption[]; quote?: FeeQuote }>

relay(to: Address.Address, data: Hex.Hex, chainId: bigint, quote?: FeeQuote): Promise<{ opHash: Hex.Hex }>
relay(to: Address.Checksummed, data: Hex.Hex, chainId: bigint, quote?: FeeQuote): Promise<{ opHash: Hex.Hex }>

status(opHash: Hex.Hex, chainId: bigint): Promise<OperationStatus>

Expand Down
Loading