diff --git a/assignments/escrow-agent/types/ethers-contracts/Counter.ts b/assignments/escrow-agent/types/ethers-contracts/Counter.ts new file mode 100644 index 00000000..b34567ad --- /dev/null +++ b/assignments/escrow-agent/types/ethers-contracts/Counter.ts @@ -0,0 +1,119 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { BaseContract, BigNumberish, BytesLike, FunctionFragment, Result, Interface, EventFragment, ContractRunner, ContractMethod, Listener } from "ethers" +import type { TypedContractEvent, TypedDeferredTopicFilter, TypedEventLog, TypedLogDescription, TypedListener, TypedContractMethod } from "./common.js" + + + export interface CounterInterface extends Interface { + getFunction(nameOrSignature: "inc" | "incBy" | "x"): FunctionFragment; + + getEvent(nameOrSignatureOrTopic: "Increment"): EventFragment; + + encodeFunctionData(functionFragment: 'inc', values?: undefined): string; +encodeFunctionData(functionFragment: 'incBy', values: [BigNumberish]): string; +encodeFunctionData(functionFragment: 'x', values?: undefined): string; + + decodeFunctionResult(functionFragment: 'inc', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'incBy', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'x', data: BytesLike): Result; + } + + + export namespace IncrementEvent { + export type InputTuple = [by: BigNumberish]; + export type OutputTuple = [by: bigint]; + export interface OutputObject {by: bigint }; + export type Event = TypedContractEvent + export type Filter = TypedDeferredTopicFilter + export type Log = TypedEventLog + export type LogDescription = TypedLogDescription + } + + + + export interface Counter extends BaseContract { + + connect(runner?: ContractRunner | null): Counter; + waitForDeployment(): Promise; + + interface: CounterInterface; + + + queryFilter( + event: TCEvent, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined, + ): Promise>> + queryFilter( + filter: TypedDeferredTopicFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + + on(event: TCEvent, listener: TypedListener): Promise + on(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + once(event: TCEvent, listener: TypedListener): Promise + once(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + listeners( + event: TCEvent + ): Promise>>; + listeners(eventName?: string): Promise> + removeAllListeners(event?: TCEvent): Promise + + + + + inc: TypedContractMethod< + [], + [void], + 'nonpayable' + > + + + + incBy: TypedContractMethod< + [by: BigNumberish, ], + [void], + 'nonpayable' + > + + + + x: TypedContractMethod< + [], + [bigint], + 'view' + > + + + + getFunction(key: string | FunctionFragment): T; + + getFunction(nameOrSignature: 'inc'): TypedContractMethod< + [], + [void], + 'nonpayable' + >; +getFunction(nameOrSignature: 'incBy'): TypedContractMethod< + [by: BigNumberish, ], + [void], + 'nonpayable' + >; +getFunction(nameOrSignature: 'x'): TypedContractMethod< + [], + [bigint], + 'view' + >; + + getEvent(key: 'Increment'): TypedContractEvent; + + filters: { + + 'Increment(uint256)': TypedContractEvent; + Increment: TypedContractEvent; + + }; + } \ No newline at end of file diff --git a/assignments/escrow-agent/types/ethers-contracts/Escrow.sol/BasicEscrow.ts b/assignments/escrow-agent/types/ethers-contracts/Escrow.sol/BasicEscrow.ts new file mode 100644 index 00000000..67efb11b --- /dev/null +++ b/assignments/escrow-agent/types/ethers-contracts/Escrow.sol/BasicEscrow.ts @@ -0,0 +1,195 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { BaseContract, BytesLike, FunctionFragment, Result, Interface, ContractRunner, ContractMethod, Listener } from "ethers" +import type { TypedContractEvent, TypedDeferredTopicFilter, TypedEventLog, TypedListener, TypedContractMethod } from "../common.js" + + + export interface BasicEscrowInterface extends Interface { + getFunction(nameOrSignature: "agent" | "amount" | "buyer" | "confirmDelivery" | "currentStatus" | "deposit" | "refundToBuyer" | "releaseToSeller" | "seller"): FunctionFragment; + + + + encodeFunctionData(functionFragment: 'agent', values?: undefined): string; +encodeFunctionData(functionFragment: 'amount', values?: undefined): string; +encodeFunctionData(functionFragment: 'buyer', values?: undefined): string; +encodeFunctionData(functionFragment: 'confirmDelivery', values?: undefined): string; +encodeFunctionData(functionFragment: 'currentStatus', values?: undefined): string; +encodeFunctionData(functionFragment: 'deposit', values?: undefined): string; +encodeFunctionData(functionFragment: 'refundToBuyer', values?: undefined): string; +encodeFunctionData(functionFragment: 'releaseToSeller', values?: undefined): string; +encodeFunctionData(functionFragment: 'seller', values?: undefined): string; + + decodeFunctionResult(functionFragment: 'agent', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'amount', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'buyer', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'confirmDelivery', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'currentStatus', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'deposit', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'refundToBuyer', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'releaseToSeller', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'seller', data: BytesLike): Result; + } + + + + export interface BasicEscrow extends BaseContract { + + connect(runner?: ContractRunner | null): BasicEscrow; + waitForDeployment(): Promise; + + interface: BasicEscrowInterface; + + + queryFilter( + event: TCEvent, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined, + ): Promise>> + queryFilter( + filter: TypedDeferredTopicFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + + on(event: TCEvent, listener: TypedListener): Promise + on(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + once(event: TCEvent, listener: TypedListener): Promise + once(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + listeners( + event: TCEvent + ): Promise>>; + listeners(eventName?: string): Promise> + removeAllListeners(event?: TCEvent): Promise + + + + + agent: TypedContractMethod< + [], + [string], + 'view' + > + + + + amount: TypedContractMethod< + [], + [bigint], + 'view' + > + + + + buyer: TypedContractMethod< + [], + [string], + 'view' + > + + + + confirmDelivery: TypedContractMethod< + [], + [void], + 'nonpayable' + > + + + + currentStatus: TypedContractMethod< + [], + [bigint], + 'view' + > + + + + deposit: TypedContractMethod< + [], + [void], + 'payable' + > + + + + refundToBuyer: TypedContractMethod< + [], + [void], + 'nonpayable' + > + + + + releaseToSeller: TypedContractMethod< + [], + [void], + 'nonpayable' + > + + + + seller: TypedContractMethod< + [], + [string], + 'view' + > + + + + getFunction(key: string | FunctionFragment): T; + + getFunction(nameOrSignature: 'agent'): TypedContractMethod< + [], + [string], + 'view' + >; +getFunction(nameOrSignature: 'amount'): TypedContractMethod< + [], + [bigint], + 'view' + >; +getFunction(nameOrSignature: 'buyer'): TypedContractMethod< + [], + [string], + 'view' + >; +getFunction(nameOrSignature: 'confirmDelivery'): TypedContractMethod< + [], + [void], + 'nonpayable' + >; +getFunction(nameOrSignature: 'currentStatus'): TypedContractMethod< + [], + [bigint], + 'view' + >; +getFunction(nameOrSignature: 'deposit'): TypedContractMethod< + [], + [void], + 'payable' + >; +getFunction(nameOrSignature: 'refundToBuyer'): TypedContractMethod< + [], + [void], + 'nonpayable' + >; +getFunction(nameOrSignature: 'releaseToSeller'): TypedContractMethod< + [], + [void], + 'nonpayable' + >; +getFunction(nameOrSignature: 'seller'): TypedContractMethod< + [], + [string], + 'view' + >; + + + + filters: { + + }; + } \ No newline at end of file diff --git a/assignments/escrow-agent/types/ethers-contracts/Escrow.sol/index.ts b/assignments/escrow-agent/types/ethers-contracts/Escrow.sol/index.ts new file mode 100644 index 00000000..4750acdd --- /dev/null +++ b/assignments/escrow-agent/types/ethers-contracts/Escrow.sol/index.ts @@ -0,0 +1,4 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +export type { BasicEscrow } from './BasicEscrow.js'; \ No newline at end of file diff --git a/assignments/escrow-agent/types/ethers-contracts/common.ts b/assignments/escrow-agent/types/ethers-contracts/common.ts new file mode 100644 index 00000000..1b4cfcbe --- /dev/null +++ b/assignments/escrow-agent/types/ethers-contracts/common.ts @@ -0,0 +1,92 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { + FunctionFragment, + Typed, + EventFragment, + ContractTransaction, + ContractTransactionResponse, + DeferredTopicFilter, + EventLog, + TransactionRequest, + LogDescription, +} from 'ethers' + +export interface TypedDeferredTopicFilter<_TCEvent extends TypedContractEvent> extends DeferredTopicFilter {} + +export interface TypedContractEvent< + InputTuple extends Array = any, + OutputTuple extends Array = any, + OutputObject = any, +> { + (...args: Partial): TypedDeferredTopicFilter> + name: string + fragment: EventFragment + getFragment(...args: Partial): EventFragment +} + +type __TypechainAOutputTuple = T extends TypedContractEvent ? W : never +type __TypechainOutputObject = T extends TypedContractEvent ? V : never + +export interface TypedEventLog extends Omit { + args: __TypechainAOutputTuple & __TypechainOutputObject +} + +export interface TypedLogDescription extends Omit { + args: __TypechainAOutputTuple & __TypechainOutputObject +} + +export type TypedListener = ( + ...listenerArg: [...__TypechainAOutputTuple, TypedEventLog, ...undefined[]] +) => void + +export type MinEthersFactory = { + deploy(...a: ARGS[]): Promise +} + +export type GetContractTypeFromFactory = F extends MinEthersFactory ? C : never +export type GetARGsTypeFromFactory = F extends MinEthersFactory ? Parameters : never + +export type StateMutability = 'nonpayable' | 'payable' | 'view' + +export type BaseOverrides = Omit +export type NonPayableOverrides = Omit +export type PayableOverrides = Omit +export type ViewOverrides = Omit +export type Overrides = S extends 'nonpayable' + ? NonPayableOverrides + : S extends 'payable' + ? PayableOverrides + : ViewOverrides + +export type PostfixOverrides, S extends StateMutability> = A | [...A, Overrides] +export type ContractMethodArgs, S extends StateMutability> = PostfixOverrides< + { [I in keyof A]-?: A[I] | Typed }, + S +> + +export type DefaultReturnType = R extends Array ? R[0] : R + +// export interface ContractMethod = Array, R = any, D extends R | ContractTransactionResponse = R | ContractTransactionResponse> { +export interface TypedContractMethod< + A extends Array = Array, + R = any, + S extends StateMutability = 'payable', +> { + (...args: ContractMethodArgs): S extends 'view' + ? Promise> + : Promise + + name: string + + fragment: FunctionFragment + + getFragment(...args: ContractMethodArgs): FunctionFragment + + populateTransaction(...args: ContractMethodArgs): Promise + staticCall(...args: ContractMethodArgs): Promise> + send(...args: ContractMethodArgs): Promise + estimateGas(...args: ContractMethodArgs): Promise + staticCallResult(...args: ContractMethodArgs): Promise +} diff --git a/assignments/escrow-agent/types/ethers-contracts/factories/Counter__factory.ts b/assignments/escrow-agent/types/ethers-contracts/factories/Counter__factory.ts new file mode 100644 index 00000000..00caab04 --- /dev/null +++ b/assignments/escrow-agent/types/ethers-contracts/factories/Counter__factory.ts @@ -0,0 +1,107 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { Addressable } from "ethers"; +import { Contract, ContractFactory, ContractTransactionResponse, Interface } from "ethers" +import type { Signer, ContractDeployTransaction, ContractRunner } from "ethers" +import type { NonPayableOverrides } from "../common.js" + import type { Counter, CounterInterface } from "../Counter.js"; + + const _abi = [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "by", + "type": "uint256" + } + ], + "name": "Increment", + "type": "event" + }, + { + "inputs": [], + "name": "inc", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "by", + "type": "uint256" + } + ], + "name": "incBy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "x", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] as const; + + const _bytecode = "0x6080604052348015600e575f5ffd5b506103cf8061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80630c55699c14610043578063371303c01461006157806370119d061461006b575b5f5ffd5b61004b610087565b6040516100589190610187565b60405180910390f35b61006961008c565b005b610085600480360381019061008091906101ce565b6100dc565b005b5f5481565b5f5f81548092919061009d90610226565b91905055507f51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a8160016040516100d291906102af565b60405180910390a1565b5f811161011e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161011590610348565b60405180910390fd5b805f5f82825461012e9190610366565b925050819055507f51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81816040516101649190610187565b60405180910390a150565b5f819050919050565b6101818161016f565b82525050565b5f60208201905061019a5f830184610178565b92915050565b5f5ffd5b6101ad8161016f565b81146101b7575f5ffd5b50565b5f813590506101c8816101a4565b92915050565b5f602082840312156101e3576101e26101a0565b5b5f6101f0848285016101ba565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6102308261016f565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610262576102616101f9565b5b600182019050919050565b5f819050919050565b5f819050919050565b5f61029961029461028f8461026d565b610276565b61016f565b9050919050565b6102a98161027f565b82525050565b5f6020820190506102c25f8301846102a0565b92915050565b5f82825260208201905092915050565b7f696e6342793a20696e6372656d656e742073686f756c6420626520706f7369745f8201527f6976650000000000000000000000000000000000000000000000000000000000602082015250565b5f6103326023836102c8565b915061033d826102d8565b604082019050919050565b5f6020820190508181035f83015261035f81610326565b9050919050565b5f6103708261016f565b915061037b8361016f565b9250828201905080821115610393576103926101f9565b5b9291505056fea26469706673582212208964bf78f883ff62c92c3c09416a09fa5a731da0068f08bc3384c0fdbe22f74f64736f6c634300081c0033"; + + + type CounterConstructorParams = [signer?: Signer] | ConstructorParameters; + + const isSuperArgs = (xs: CounterConstructorParams): xs is ConstructorParameters => + xs.length > 1 + + + export class Counter__factory extends ContractFactory { + + constructor(...args: CounterConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + + } + + override getDeployTransaction(overrides?: NonPayableOverrides & { from?: string }): Promise { + return super.getDeployTransaction(overrides || {}); + }; + override deploy(overrides?: NonPayableOverrides & { from?: string }) { + return super.deploy(overrides || {}) as Promise; + } + override connect(runner: ContractRunner | null): Counter__factory { + return super.connect(runner) as Counter__factory; + } + + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): CounterInterface { + return new Interface(_abi) as CounterInterface; + } + + override attach(address: string | Addressable): Counter { + return super.attach(address) as Counter; + } + static connect(address: string, runner?: ContractRunner | null): Counter { + return new Contract(address, _abi, runner) as unknown as Counter; + } + } + + + \ No newline at end of file diff --git a/assignments/escrow-agent/types/ethers-contracts/factories/Escrow.sol/BasicEscrow__factory.ts b/assignments/escrow-agent/types/ethers-contracts/factories/Escrow.sol/BasicEscrow__factory.ts new file mode 100644 index 00000000..162021c3 --- /dev/null +++ b/assignments/escrow-agent/types/ethers-contracts/factories/Escrow.sol/BasicEscrow__factory.ts @@ -0,0 +1,170 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { Addressable } from "ethers"; +import { Contract, ContractFactory, ContractTransactionResponse, Interface } from "ethers" +import type { Signer, AddressLike, ContractDeployTransaction, ContractRunner } from "ethers" +import type { NonPayableOverrides } from "../../common.js" + import type { BasicEscrow, BasicEscrowInterface } from "../../Escrow.sol/BasicEscrow.js"; + + const _abi = [ + { + "inputs": [ + { + "internalType": "address", + "name": "_buyer", + "type": "address" + }, + { + "internalType": "address", + "name": "_seller", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "agent", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "amount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "buyer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "confirmDelivery", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentStatus", + "outputs": [ + { + "internalType": "enum BasicEscrow.Status", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "refundToBuyer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseToSeller", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "seller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] as const; + + const _bytecode = "0x608060405234801561000f575f5ffd5b50604051610d5e380380610d5e83398181016040528101906100319190610155565b3360025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550815f5f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050610193565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610124826100fb565b9050919050565b6101348161011a565b811461013e575f5ffd5b50565b5f8151905061014f8161012b565b92915050565b5f5f6040838503121561016b5761016a6100f7565b5b5f61017885828601610141565b925050602061018985828601610141565b9150509250929050565b610bbe806101a05f395ff3fe608060405260043610610085575f3560e01c8063892a0e4211610058578063892a0e4214610109578063aa8c217c1461011f578063d0e30db014610149578063ef8a923514610153578063f5ff5c761461017d57610085565b806308551a53146100895780634bd7d081146100b35780635e10177b146100c95780637150d8ae146100df575b5f5ffd5b348015610094575f5ffd5b5061009d6101a7565b6040516100aa91906107ca565b60405180910390f35b3480156100be575f5ffd5b506100c76101cc565b005b3480156100d4575f5ffd5b506100dd610362565b005b3480156100ea575f5ffd5b506100f3610491565b60405161010091906107ca565b60405180910390f35b348015610114575f5ffd5b5061011d6104b5565b005b34801561012a575f5ffd5b5061013361064c565b60405161014091906107fb565b60405180910390f35b610151610652565b005b34801561015e575f5ffd5b50610167610754565b6040516101749190610887565b60405180910390f35b348015610188575f5ffd5b50610191610766565b60405161019e91906107ca565b60405180910390f35b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461025b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610252906108fa565b60405180910390fd5b6002600481111561026f5761026e610814565b5b60045f9054906101000a900460ff1660048111156102905761028f610814565b5b036102d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102c790610962565b60405180910390fd5b600360045f6101000a81548160ff021916908360048111156102f5576102f4610814565b5b02179055505f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc60035490811502906040515f60405180830381858888f1935050505015801561035f573d5f5f3e3d5ffd5b50565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146103f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103e8906109ca565b60405180910390fd5b5f600481111561040457610403610814565b5b60045f9054906101000a900460ff16600481111561042557610424610814565b5b14610465576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045c90610a32565b60405180910390fd5b600160045f6101000a81548160ff0219169083600481111561048a57610489610814565b5b0217905550565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161053b906108fa565b60405180910390fd5b6001600481111561055857610557610814565b5b60045f9054906101000a900460ff16600481111561057957610578610814565b5b146105b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105b090610a9a565b60405180910390fd5b600260045f6101000a81548160ff021916908360048111156105de576105dd610814565b5b021790555060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc60035490811502906040515f60405180830381858888f19350505050158015610649573d5f5f3e3d5ffd5b50565b60035481565b5f5f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146106e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106d790610b02565b60405180910390fd5b5f3411610722576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161071990610b6a565b60405180910390fd5b346003819055505f60045f6101000a81548160ff0219169083600481111561074d5761074c610814565b5b0217905550565b60045f9054906101000a900460ff1681565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6107b48261078b565b9050919050565b6107c4816107aa565b82525050565b5f6020820190506107dd5f8301846107bb565b92915050565b5f819050919050565b6107f5816107e3565b82525050565b5f60208201905061080e5f8301846107ec565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6005811061085257610851610814565b5b50565b5f81905061086282610841565b919050565b5f61087182610855565b9050919050565b61088181610867565b82525050565b5f60208201905061089a5f830184610878565b92915050565b5f82825260208201905092915050565b7f4f6e6c79204167656e742063616e2063616c6c207468697300000000000000005f82015250565b5f6108e46018836108a0565b91506108ef826108b0565b602082019050919050565b5f6020820190508181035f830152610911816108d8565b9050919050565b7f416c726561647920636f6d706c657465640000000000000000000000000000005f82015250565b5f61094c6011836108a0565b915061095782610918565b602082019050919050565b5f6020820190508181035f83015261097981610940565b9050919050565b7f4f6e6c792053656c6c65722063616e2063616c6c2074686973000000000000005f82015250565b5f6109b46019836108a0565b91506109bf82610980565b602082019050919050565b5f6020820190508181035f8301526109e1816109a8565b9050919050565b7f496e76616c6964207374617465000000000000000000000000000000000000005f82015250565b5f610a1c600d836108a0565b9150610a27826109e8565b602082019050919050565b5f6020820190508181035f830152610a4981610a10565b9050919050565b7f4974656d206e6f742073686970706564207965740000000000000000000000005f82015250565b5f610a846014836108a0565b9150610a8f82610a50565b602082019050919050565b5f6020820190508181035f830152610ab181610a78565b9050919050565b7f4f6e6c792042757965722063616e2063616c6c207468697300000000000000005f82015250565b5f610aec6018836108a0565b9150610af782610ab8565b602082019050919050565b5f6020820190508181035f830152610b1981610ae0565b9050919050565b7f4d757374206465706f73697420736f6d652045544800000000000000000000005f82015250565b5f610b546015836108a0565b9150610b5f82610b20565b602082019050919050565b5f6020820190508181035f830152610b8181610b48565b905091905056fea26469706673582212203bc18ae3493df6d886e8a198f667e02246405b7ec526c503dbb0cf9c1fc4900264736f6c634300081c0033"; + + + type BasicEscrowConstructorParams = [signer?: Signer] | ConstructorParameters; + + const isSuperArgs = (xs: BasicEscrowConstructorParams): xs is ConstructorParameters => + xs.length > 1 + + + export class BasicEscrow__factory extends ContractFactory { + + constructor(...args: BasicEscrowConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + + } + + override getDeployTransaction(_buyer: AddressLike, _seller: AddressLike, overrides?: NonPayableOverrides & { from?: string }): Promise { + return super.getDeployTransaction(_buyer, _seller, overrides || {}); + }; + override deploy(_buyer: AddressLike, _seller: AddressLike, overrides?: NonPayableOverrides & { from?: string }) { + return super.deploy(_buyer, _seller, overrides || {}) as Promise; + } + override connect(runner: ContractRunner | null): BasicEscrow__factory { + return super.connect(runner) as BasicEscrow__factory; + } + + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): BasicEscrowInterface { + return new Interface(_abi) as BasicEscrowInterface; + } + + override attach(address: string | Addressable): BasicEscrow { + return super.attach(address) as BasicEscrow; + } + static connect(address: string, runner?: ContractRunner | null): BasicEscrow { + return new Contract(address, _abi, runner) as unknown as BasicEscrow; + } + } + + + \ No newline at end of file diff --git a/assignments/escrow-agent/types/ethers-contracts/factories/Escrow.sol/index.ts b/assignments/escrow-agent/types/ethers-contracts/factories/Escrow.sol/index.ts new file mode 100644 index 00000000..6e6913b9 --- /dev/null +++ b/assignments/escrow-agent/types/ethers-contracts/factories/Escrow.sol/index.ts @@ -0,0 +1,4 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +export { BasicEscrow__factory } from './BasicEscrow__factory.js'; \ No newline at end of file diff --git a/assignments/escrow-agent/types/ethers-contracts/factories/index.ts b/assignments/escrow-agent/types/ethers-contracts/factories/index.ts new file mode 100644 index 00000000..089508b8 --- /dev/null +++ b/assignments/escrow-agent/types/ethers-contracts/factories/index.ts @@ -0,0 +1,5 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +export * as escrowSol from './Escrow.sol/index.js'; +export { Counter__factory } from './Counter__factory.js'; \ No newline at end of file diff --git a/assignments/escrow-agent/types/ethers-contracts/hardhat.d.ts b/assignments/escrow-agent/types/ethers-contracts/hardhat.d.ts new file mode 100644 index 00000000..5e9b63ed --- /dev/null +++ b/assignments/escrow-agent/types/ethers-contracts/hardhat.d.ts @@ -0,0 +1,51 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ + + +import { ethers } from 'ethers' +import { DeployContractOptions, FactoryOptions, HardhatEthersHelpers as HardhatEthersHelpersBase} from "@nomicfoundation/hardhat-ethers/types"; + +import * as Contracts from "./index.js"; + +declare module "@nomicfoundation/hardhat-ethers/types" { + interface HardhatEthersHelpers extends HardhatEthersHelpersBase { + getContractFactory(name: 'Counter', signerOrOptions?: ethers.Signer | FactoryOptions): Promise +getContractFactory(name: 'BasicEscrow', signerOrOptions?: ethers.Signer | FactoryOptions): Promise + + getContractAt(name: 'Counter', address: string | ethers.Addressable, signer?: ethers.Signer): Promise +getContractAt(name: 'BasicEscrow', address: string | ethers.Addressable, signer?: ethers.Signer): Promise + + deployContract(name: 'Counter', signerOrOptions?: ethers.Signer | DeployContractOptions): Promise +deployContract(name: 'BasicEscrow', signerOrOptions?: ethers.Signer | DeployContractOptions): Promise + + deployContract(name: 'Counter', args: any[], signerOrOptions?: ethers.Signer | DeployContractOptions): Promise +deployContract(name: 'BasicEscrow', args: any[], signerOrOptions?: ethers.Signer | DeployContractOptions): Promise + + // default types + getContractFactory( + name: string, + signerOrOptions?: ethers.Signer | FactoryOptions + ): Promise; + getContractFactory( + abi: any[], + bytecode: ethers.BytesLike, + signer?: ethers.Signer + ): Promise; + getContractAt( + nameOrAbi: string | any[], + address: string | ethers.Addressable, + signer?: ethers.Signer + ): Promise; + deployContract( + name: string, + signerOrOptions?: ethers.Signer | DeployContractOptions + ): Promise; + deployContract( + name: string, + args: any[], + signerOrOptions?: ethers.Signer | DeployContractOptions + ): Promise; + } +} + \ No newline at end of file diff --git a/assignments/escrow-agent/types/ethers-contracts/index.ts b/assignments/escrow-agent/types/ethers-contracts/index.ts new file mode 100644 index 00000000..dfc6ab08 --- /dev/null +++ b/assignments/escrow-agent/types/ethers-contracts/index.ts @@ -0,0 +1,10 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type * as escrowSol from './Escrow.sol/index.js'; +export type { escrowSol }; +export type { Counter } from './Counter.js'; +export * as factories from './factories/index.js'; +export { Counter__factory } from './factories/Counter__factory.js'; +export type { BasicEscrow } from './Escrow.sol/BasicEscrow.js'; +export { BasicEscrow__factory } from './factories/Escrow.sol/BasicEscrow__factory.js'; \ No newline at end of file diff --git a/assignments/founder/counter/.github/workflows/test.yml b/assignments/founder/counter/.github/workflows/test.yml new file mode 100644 index 00000000..b79c8d4f --- /dev/null +++ b/assignments/founder/counter/.github/workflows/test.yml @@ -0,0 +1,38 @@ +name: CI + +permissions: {} + +on: + push: + pull_request: + workflow_dispatch: + +env: + FOUNDRY_PROFILE: ci + +jobs: + check: + name: Foundry project + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v5 + with: + persist-credentials: false + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Show Forge version + run: forge --version + + - name: Run Forge fmt + run: forge fmt --check + + - name: Run Forge build + run: forge build --sizes + + - name: Run Forge tests + run: forge test -vvv diff --git a/assignments/founder/counter/.gitignore b/assignments/founder/counter/.gitignore new file mode 100644 index 00000000..8e0a27eb --- /dev/null +++ b/assignments/founder/counter/.gitignore @@ -0,0 +1,20 @@ +# Compiler files +cache/ +out/ + +# Ignores development broadcast logs +!/broadcast +/broadcast/*/31337/ +/broadcast/**/dry-run/ + +# Docs +docs/ + +# Dotenv file +.env + + +cache/ +lib/ +out/ + diff --git a/assignments/founder/counter/README.md b/assignments/founder/counter/README.md new file mode 100644 index 00000000..8817d6ab --- /dev/null +++ b/assignments/founder/counter/README.md @@ -0,0 +1,66 @@ +## Foundry + +**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** + +Foundry consists of: + +- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). +- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. +- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. +- **Chisel**: Fast, utilitarian, and verbose solidity REPL. + +## Documentation + +https://book.getfoundry.sh/ + +## Usage + +### Build + +```shell +$ forge build +``` + +### Test + +```shell +$ forge test +``` + +### Format + +```shell +$ forge fmt +``` + +### Gas Snapshots + +```shell +$ forge snapshot +``` + +### Anvil + +```shell +$ anvil +``` + +### Deploy + +```shell +$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key +``` + +### Cast + +```shell +$ cast +``` + +### Help + +```shell +$ forge --help +$ anvil --help +$ cast --help +``` diff --git a/assignments/founder/counter/foundry.lock b/assignments/founder/counter/foundry.lock new file mode 100644 index 00000000..bc06b89b --- /dev/null +++ b/assignments/founder/counter/foundry.lock @@ -0,0 +1,8 @@ +{ + "lib/forge-std": { + "tag": { + "name": "v1.15.0", + "rev": "0844d7e1fc5e60d77b68e469bff60265f236c398" + } + } +} \ No newline at end of file diff --git a/assignments/founder/counter/foundry.toml b/assignments/founder/counter/foundry.toml new file mode 100644 index 00000000..eed5fdde --- /dev/null +++ b/assignments/founder/counter/foundry.toml @@ -0,0 +1,7 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] +remappings = ["forge-std/=lib/forge-std/src/"] + +# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/assignments/founder/counter/remappings.txt b/assignments/founder/counter/remappings.txt new file mode 100644 index 00000000..feaba2dd --- /dev/null +++ b/assignments/founder/counter/remappings.txt @@ -0,0 +1 @@ +forge-std/=lib/forge-std/src/ diff --git a/assignments/founder/counter/src/TimeLock2.sol b/assignments/founder/counter/src/TimeLock2.sol new file mode 100644 index 00000000..34ccb235 --- /dev/null +++ b/assignments/founder/counter/src/TimeLock2.sol @@ -0,0 +1,152 @@ +//SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +contract TimeLock { + struct Vault { + uint balance; + uint unlockTime; + bool active; + } + + + mapping(address => Vault[]) private vaults; + + event Deposited(address indexed user, uint vaultId, uint amount, uint unlockTime); + event Withdrawn(address indexed user, uint vaultId, uint amount); + + function deposit(uint _unlockTime) external payable returns (uint) { + require(msg.value > 0, "Deposit must be greater than zero"); + require(_unlockTime > block.timestamp, "Unlock time must be in the future"); + + // Create new vault + vaults[msg.sender].push(Vault({ + balance: msg.value, + unlockTime: _unlockTime, + active: true + })); + + uint vaultId = vaults[msg.sender].length - 1; + emit Deposited(msg.sender, vaultId, msg.value, _unlockTime); + + return vaultId; + } +function withdraw(uint _vaultId) external { + require(_vaultId < vaults[msg.sender].length, "Invalid vault ID"); + + Vault storage userVault = vaults[msg.sender][_vaultId]; + require(userVault.active, "Vault is not active"); + require(userVault.balance > 0, "Vault has zero balance"); + require(block.timestamp >= userVault.unlockTime, "Funds are still locked"); + + uint amount = userVault.balance; + + // Mark vault as inactive and clear balance + userVault.balance = 0; + userVault.active = false; + + (bool success, ) = payable(msg.sender).call{value: amount}(""); + require(success, "Transfer failed"); + + emit Withdrawn(msg.sender, _vaultId, amount); + } + function withdrawAll() external returns (uint) { + uint totalWithdrawn = 0; + Vault[] storage userVaults = vaults[msg.sender]; + + for (uint i = 0; i < userVaults.length; i++) { + if (userVaults[i].active && + userVaults[i].balance > 0 && + block.timestamp >= userVaults[i].unlockTime) { + + uint amount = userVaults[i].balance; + userVaults[i].balance = 0; + userVaults[i].active = false; + + totalWithdrawn += amount; + emit Withdrawn(msg.sender, i, amount); + } + } + + require(totalWithdrawn > 0, "No unlocked funds available"); + + (bool success, ) = payable(msg.sender).call{value: totalWithdrawn}(""); + require(success, "Transfer failed"); + + return totalWithdrawn; + } + function getVaultCount(address _user) external view returns (uint) { + return vaults[_user].length; + } + function getVault(address _user, uint _vaultId) external view returns ( + uint balance, + uint unlockTime, + bool active, + bool isUnlocked + ) { + require(_vaultId < vaults[_user].length, "Invalid vault ID"); + + Vault storage vault = vaults[_user][_vaultId]; + return ( + vault.balance, + vault.unlockTime, + vault.active, + block.timestamp >= vault.unlockTime + ); + } + function getAllVaults(address _user) external view returns (Vault[] memory) { + return vaults[_user]; + } + function getActiveVaults(address _user) external view returns ( + uint[] memory activeVaults, + uint[] memory balances, + uint[] memory unlockTimes + ) { + Vault[] storage userVaults = vaults[_user]; + + // Count active vaults + uint activeCount = 0; + for (uint i = 0; i < userVaults.length; i++) { + if (userVaults[i].active && userVaults[i].balance > 0) { + activeCount++; + } + } + + // Create arrays + activeVaults = new uint[](activeCount); + balances = new uint[](activeCount); + unlockTimes = new uint[](activeCount); + + // Populate arrays + uint index = 0; + for (uint i = 0; i < userVaults.length; i++) { + if (userVaults[i].active && userVaults[i].balance > 0) { + activeVaults[index] = i; + balances[index] = userVaults[i].balance; + unlockTimes[index] = userVaults[i].unlockTime; + index++; + } + } + + return (activeVaults, balances, unlockTimes); + } + function getTotalBalance(address _user) external view returns (uint total) { + Vault[] storage userVaults = vaults[_user]; + for (uint i = 0; i < userVaults.length; i++) { + if (userVaults[i].active) { + total += userVaults[i].balance; + } + } + return total; + } + function getUnlockedBalance(address _user) external view returns (uint unlocked) { + Vault[] storage userVaults = vaults[_user]; + for (uint i = 0; i < userVaults.length; i++) { + if (userVaults[i].active && + userVaults[i].balance > 0 && + block.timestamp >= userVaults[i].unlockTime) { + unlocked += userVaults[i].balance; + } + } + return unlocked; + } +} diff --git a/assignments/founder/counter/test/TimeLock2.t.sol b/assignments/founder/counter/test/TimeLock2.t.sol new file mode 100644 index 00000000..5948a50e --- /dev/null +++ b/assignments/founder/counter/test/TimeLock2.t.sol @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.28; + +import {Test} from "forge-std/Test.sol"; +import {TimeLock} from "../src/TimeLock2.sol"; + +contract TimeLock2Test is Test { + TimeLock public timelock; + + uint256 internal constant ONE_DAY_IN_SECS = 24 * 60 * 60; + uint256 internal constant DEPOSIT_AMOUNT = 1 ether; + + event Deposited(address indexed user, uint256 vaultId, uint256 amount, uint256 unlockTime); + event Withdrawn(address indexed user, uint256 vaultId, uint256 amount); + + receive() external payable {} + + function setUp() public { + timelock = new TimeLock(); + vm.deal(address(this), 100 ether); + } + + function test_ShouldCreateVaultWithCorrectBalanceAndUnlockTime() public { + uint256 unlockTime = block.timestamp + ONE_DAY_IN_SECS; + + vm.expectEmit(true, false, false, true); + emit Deposited(address(this), 0, DEPOSIT_AMOUNT, unlockTime); + timelock.deposit{value: DEPOSIT_AMOUNT}(unlockTime); + + (uint256 balance, uint256 storedUnlockTime, bool active, ) = timelock.getVault(address(this), 0); + assertEq(balance, DEPOSIT_AMOUNT); + assertEq(storedUnlockTime, unlockTime); + assertTrue(active); + } + + function test_ShouldRevertIfDepositIs0() public { + uint256 unlockTime = block.timestamp + ONE_DAY_IN_SECS; + + vm.expectRevert("Deposit must be greater than zero"); + timelock.deposit{value: 0}(unlockTime); + } + + function test_ShouldRevertIfUnlockTimeIsInThePast() public { + uint256 pastTime = block.timestamp; + + vm.expectRevert("Unlock time must be in the future"); + timelock.deposit{value: DEPOSIT_AMOUNT}(pastTime); + } + + function test_ShouldFailIfFundsAreStillLocked() public { + uint256 unlockTime = block.timestamp + ONE_DAY_IN_SECS; + + timelock.deposit{value: DEPOSIT_AMOUNT}(unlockTime); + + vm.expectRevert("Funds are still locked"); + timelock.withdraw(0); + } + + function test_ShouldSucceedIfUnlockTimeHasPassed() public { + uint256 unlockTime = block.timestamp + ONE_DAY_IN_SECS; + + timelock.deposit{value: DEPOSIT_AMOUNT}(unlockTime); + + vm.warp(unlockTime); + + vm.expectEmit(true, false, false, true); + emit Withdrawn(address(this), 0, DEPOSIT_AMOUNT); + timelock.withdraw(0); + + (uint256 balance, , bool active, ) = timelock.getVault(address(this), 0); + assertFalse(active); + assertEq(balance, 0); + } + + function test_ShouldFailIfTryingToWithdrawFromAnInactiveVault() public { + uint256 unlockTime = block.timestamp + ONE_DAY_IN_SECS; + + timelock.deposit{value: DEPOSIT_AMOUNT}(unlockTime); + vm.warp(unlockTime); + timelock.withdraw(0); + + vm.expectRevert("Vault is not active"); + timelock.withdraw(0); + } + + function test_ShouldWithdrawFromMultipleUnlockedVaultsAtOnce() public { + uint256 nowTime = block.timestamp; + + timelock.deposit{value: DEPOSIT_AMOUNT}(nowTime + ONE_DAY_IN_SECS); + timelock.deposit{value: DEPOSIT_AMOUNT}(nowTime + ONE_DAY_IN_SECS * 2); + timelock.deposit{value: DEPOSIT_AMOUNT}(nowTime + ONE_DAY_IN_SECS * 10); + + vm.warp(nowTime + ONE_DAY_IN_SECS * 3); + + uint256 expectedTransfer = DEPOSIT_AMOUNT * 2; + uint256 balanceBefore = address(this).balance; + + uint256 withdrawn = timelock.withdrawAll(); + + assertEq(withdrawn, expectedTransfer); + assertEq(address(this).balance, balanceBefore + expectedTransfer); + assertEq(timelock.getTotalBalance(address(this)), DEPOSIT_AMOUNT); + } + + function test_ShouldRevertIfNoVaultsAreReadyForWithdrawal() public { + uint256 unlockTime = block.timestamp + ONE_DAY_IN_SECS; + + timelock.deposit{value: DEPOSIT_AMOUNT}(unlockTime); + + vm.expectRevert("No unlocked funds available"); + timelock.withdrawAll(); + } + + function test_ShouldCorrectlyTrackTotalAndUnlockedBalances() public { + uint256 nowTime = block.timestamp; + + timelock.deposit{value: 1 ether}(nowTime + 100); + timelock.deposit{value: 2 ether}(nowTime + 1000); + + assertEq(timelock.getTotalBalance(address(this)), 3 ether); + assertEq(timelock.getUnlockedBalance(address(this)), 0); + + vm.warp(nowTime + 200); + assertEq(timelock.getUnlockedBalance(address(this)), 1 ether); + } + + function test_ShouldReturnOnlyActiveVaultsData() public { + uint256 nowTime = block.timestamp; + + timelock.deposit{value: DEPOSIT_AMOUNT}(nowTime + 100); + timelock.deposit{value: DEPOSIT_AMOUNT}(nowTime + 200); + + vm.warp(nowTime + 150); + timelock.withdraw(0); + + (uint256[] memory activeVaults, , ) = timelock.getActiveVaults(address(this)); + assertEq(activeVaults.length, 1); + assertEq(activeVaults[0], 1); + } +} diff --git a/assignments/founder/foundry-documentation.md b/assignments/founder/foundry-documentation.md new file mode 100644 index 00000000..18ec7245 --- /dev/null +++ b/assignments/founder/foundry-documentation.md @@ -0,0 +1,196 @@ +# Foundry – Getting Started + +## Overview + +Foundry is a toolkit for building, testing, and deploying Ethereum smart contracts. It works from the command line and is known for being fast and simple to use. + +It helps me: + +* Write smart contracts +* Compile them +* Run tests +* Deploy contracts +* Interact with the blockchain +* Run a local Ethereum network + +--- + +# Tools Included in Foundry + +Foundry comes with four main tools: + +## Forge + +Used to: + +* Build smart contracts +* Run tests +* Deploy contracts +* Manage projects + +## Cast + +Used to: + +* Send transactions +* Call smart contract functions +* Check balances +* Read blockchain data + +## Anvil + +Used to: + +* Run a local Ethereum blockchain +* Test deployments locally +* Work with pre-funded test accounts + +## Chisel + +Used to: + +* Test small Solidity snippets quickly +* Experiment with Solidity code + +--- + +# Installation + +To install Foundry: + +```bash +curl -L https://foundry.paradigm.xyz | bash +foundryup +``` + +After installation, the following commands become available: + +* `forge` +* `cast` +* `anvil` +* `chisel` + +--- + +# Creating a New Project + +To create a new Foundry project: + +```bash +forge init my_project +cd my_project +``` + +This creates a project structure like this: + +``` +my_project/ +│ +├── src/ → Smart contracts +├── test/ → Test files +├── script/ → Deployment scripts +└── foundry.toml → Configuration file +``` + +--- + +# Building Contracts + +To compile smart contracts: + +```bash +forge build +``` + +This checks for errors and compiles the contracts. + +--- + +# Running Tests + +To run tests: + +```bash +forge test +``` + +This command: + +* Runs all test files +* Shows which tests passed +* Shows which tests failed +* Displays gas usage + +--- + +# Deploying Contracts + +Contracts can be deployed using scripts: + +```bash +forge script script/Example.s.sol +``` + +To deploy to a real network, I need: + +* A private key +* An RPC URL + +--- + +# Running a Local Blockchain + +To start a local Ethereum network: + +```bash +anvil +``` + +This: + +* Creates test accounts +* Gives them fake ETH +* Allows local testing of deployments and transactions + +--- + +# Using Cast to Interact with Blockchain + +Example: Check account balance + +```bash +cast balance
--ether --rpc-url +``` + +With `cast`, I can: + +* Call contract functions +* Send transactions +* Check block information +* Read on-chain data + +--- + +# Using Chisel + +Start Chisel: + +```bash +chisel +``` + +It allows testing small Solidity code instantly without creating a full contract. + +Example: + +uint x = 5; + +# What I Learned + +* How to install Foundry +* How to create a new project +* How to compile contracts +* How to run tests +* How to deploy contracts +* How to run a local blockchain +* How to interact with Ethereum from the command line diff --git a/assignments/todo/types/ethers-contracts/Bank.ts b/assignments/todo/types/ethers-contracts/Bank.ts new file mode 100644 index 00000000..9302e586 --- /dev/null +++ b/assignments/todo/types/ethers-contracts/Bank.ts @@ -0,0 +1,164 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { BaseContract, BigNumberish, BytesLike, FunctionFragment, Result, Interface, EventFragment, AddressLike, ContractRunner, ContractMethod, Listener } from "ethers" +import type { TypedContractEvent, TypedDeferredTopicFilter, TypedEventLog, TypedLogDescription, TypedListener, TypedContractMethod } from "./common.js" + + + export interface BankInterface extends Interface { + getFunction(nameOrSignature: "balances" | "deposit" | "drain" | "re" | "totalBalance" | "withdraw"): FunctionFragment; + + getEvent(nameOrSignatureOrTopic: "depositSuccessful"): EventFragment; + + encodeFunctionData(functionFragment: 'balances', values: [AddressLike]): string; +encodeFunctionData(functionFragment: 'deposit', values?: undefined): string; +encodeFunctionData(functionFragment: 'drain', values: [AddressLike]): string; +encodeFunctionData(functionFragment: 're', values?: undefined): string; +encodeFunctionData(functionFragment: 'totalBalance', values?: undefined): string; +encodeFunctionData(functionFragment: 'withdraw', values: [BigNumberish]): string; + + decodeFunctionResult(functionFragment: 'balances', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'deposit', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'drain', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 're', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'totalBalance', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'withdraw', data: BytesLike): Result; + } + + + export namespace depositSuccessfulEvent { + export type InputTuple = [sent: string, amount: BigNumberish]; + export type OutputTuple = [sent: string, amount: bigint]; + export interface OutputObject {sent: string, amount: bigint }; + export type Event = TypedContractEvent + export type Filter = TypedDeferredTopicFilter + export type Log = TypedEventLog + export type LogDescription = TypedLogDescription + } + + + + export interface Bank extends BaseContract { + + connect(runner?: ContractRunner | null): Bank; + waitForDeployment(): Promise; + + interface: BankInterface; + + + queryFilter( + event: TCEvent, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined, + ): Promise>> + queryFilter( + filter: TypedDeferredTopicFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + + on(event: TCEvent, listener: TypedListener): Promise + on(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + once(event: TCEvent, listener: TypedListener): Promise + once(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + listeners( + event: TCEvent + ): Promise>>; + listeners(eventName?: string): Promise> + removeAllListeners(event?: TCEvent): Promise + + + + + balances: TypedContractMethod< + [arg0: AddressLike, ], + [bigint], + 'view' + > + + + + deposit: TypedContractMethod< + [], + [boolean], + 'payable' + > + + + + drain: TypedContractMethod< + [recepient: AddressLike, ], + [void], + 'nonpayable' + > + + + + re: TypedContractMethod< + [], + [string], + 'view' + > + + + + totalBalance: TypedContractMethod< + [], + [bigint], + 'view' + > + + + + withdraw: TypedContractMethod< + [_amount: BigNumberish, ], + [void], + 'nonpayable' + > + + + + getFunction(key: string | FunctionFragment): T; + + getFunction(nameOrSignature: 'balances'): TypedContractMethod< + [arg0: AddressLike, ], + [bigint], + 'view' + >; +getFunction(nameOrSignature: 'deposit'): TypedContractMethod< + [], + [boolean], + 'payable' + >; +getFunction(nameOrSignature: 'drain'): TypedContractMethod< + [recepient: AddressLike, ], + [void], + 'nonpayable' + >; +getFunction(nameOrSignature: 're'): TypedContractMethod< + [], + [string], + 'view' + >; +getFunction(nameOrSignature: 'totalBalance'): TypedContractMethod< + [], + [bigint], + 'view' + >; +getFunction(nameOrSignature: 'withdraw'): TypedContractMethod< + [_amount: BigNumberish, ], + [void], + 'nonpayable' + >; + + getEvent(key: 'depositSuccessful'): TypedContractEvent; + + filters: { + + 'depositSuccessful(string,uint256)': TypedContractEvent; + depositSuccessful: TypedContractEvent; + + }; + } \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/Counter.ts b/assignments/todo/types/ethers-contracts/Counter.ts new file mode 100644 index 00000000..b34567ad --- /dev/null +++ b/assignments/todo/types/ethers-contracts/Counter.ts @@ -0,0 +1,119 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { BaseContract, BigNumberish, BytesLike, FunctionFragment, Result, Interface, EventFragment, ContractRunner, ContractMethod, Listener } from "ethers" +import type { TypedContractEvent, TypedDeferredTopicFilter, TypedEventLog, TypedLogDescription, TypedListener, TypedContractMethod } from "./common.js" + + + export interface CounterInterface extends Interface { + getFunction(nameOrSignature: "inc" | "incBy" | "x"): FunctionFragment; + + getEvent(nameOrSignatureOrTopic: "Increment"): EventFragment; + + encodeFunctionData(functionFragment: 'inc', values?: undefined): string; +encodeFunctionData(functionFragment: 'incBy', values: [BigNumberish]): string; +encodeFunctionData(functionFragment: 'x', values?: undefined): string; + + decodeFunctionResult(functionFragment: 'inc', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'incBy', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'x', data: BytesLike): Result; + } + + + export namespace IncrementEvent { + export type InputTuple = [by: BigNumberish]; + export type OutputTuple = [by: bigint]; + export interface OutputObject {by: bigint }; + export type Event = TypedContractEvent + export type Filter = TypedDeferredTopicFilter + export type Log = TypedEventLog + export type LogDescription = TypedLogDescription + } + + + + export interface Counter extends BaseContract { + + connect(runner?: ContractRunner | null): Counter; + waitForDeployment(): Promise; + + interface: CounterInterface; + + + queryFilter( + event: TCEvent, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined, + ): Promise>> + queryFilter( + filter: TypedDeferredTopicFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + + on(event: TCEvent, listener: TypedListener): Promise + on(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + once(event: TCEvent, listener: TypedListener): Promise + once(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + listeners( + event: TCEvent + ): Promise>>; + listeners(eventName?: string): Promise> + removeAllListeners(event?: TCEvent): Promise + + + + + inc: TypedContractMethod< + [], + [void], + 'nonpayable' + > + + + + incBy: TypedContractMethod< + [by: BigNumberish, ], + [void], + 'nonpayable' + > + + + + x: TypedContractMethod< + [], + [bigint], + 'view' + > + + + + getFunction(key: string | FunctionFragment): T; + + getFunction(nameOrSignature: 'inc'): TypedContractMethod< + [], + [void], + 'nonpayable' + >; +getFunction(nameOrSignature: 'incBy'): TypedContractMethod< + [by: BigNumberish, ], + [void], + 'nonpayable' + >; +getFunction(nameOrSignature: 'x'): TypedContractMethod< + [], + [bigint], + 'view' + >; + + getEvent(key: 'Increment'): TypedContractEvent; + + filters: { + + 'Increment(uint256)': TypedContractEvent; + Increment: TypedContractEvent; + + }; + } \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/Todo.sol/Bank.ts b/assignments/todo/types/ethers-contracts/Todo.sol/Bank.ts new file mode 100644 index 00000000..c14e6fa0 --- /dev/null +++ b/assignments/todo/types/ethers-contracts/Todo.sol/Bank.ts @@ -0,0 +1,164 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { BaseContract, BigNumberish, BytesLike, FunctionFragment, Result, Interface, EventFragment, AddressLike, ContractRunner, ContractMethod, Listener } from "ethers" +import type { TypedContractEvent, TypedDeferredTopicFilter, TypedEventLog, TypedLogDescription, TypedListener, TypedContractMethod } from "../common.js" + + + export interface BankInterface extends Interface { + getFunction(nameOrSignature: "balances" | "deposit" | "drain" | "re" | "totalBalance" | "withdraw"): FunctionFragment; + + getEvent(nameOrSignatureOrTopic: "depositSuccessful"): EventFragment; + + encodeFunctionData(functionFragment: 'balances', values: [AddressLike]): string; +encodeFunctionData(functionFragment: 'deposit', values?: undefined): string; +encodeFunctionData(functionFragment: 'drain', values: [AddressLike]): string; +encodeFunctionData(functionFragment: 're', values?: undefined): string; +encodeFunctionData(functionFragment: 'totalBalance', values?: undefined): string; +encodeFunctionData(functionFragment: 'withdraw', values: [BigNumberish]): string; + + decodeFunctionResult(functionFragment: 'balances', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'deposit', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'drain', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 're', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'totalBalance', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'withdraw', data: BytesLike): Result; + } + + + export namespace depositSuccessfulEvent { + export type InputTuple = [sent: string, amount: BigNumberish]; + export type OutputTuple = [sent: string, amount: bigint]; + export interface OutputObject {sent: string, amount: bigint }; + export type Event = TypedContractEvent + export type Filter = TypedDeferredTopicFilter + export type Log = TypedEventLog + export type LogDescription = TypedLogDescription + } + + + + export interface Bank extends BaseContract { + + connect(runner?: ContractRunner | null): Bank; + waitForDeployment(): Promise; + + interface: BankInterface; + + + queryFilter( + event: TCEvent, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined, + ): Promise>> + queryFilter( + filter: TypedDeferredTopicFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + + on(event: TCEvent, listener: TypedListener): Promise + on(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + once(event: TCEvent, listener: TypedListener): Promise + once(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + listeners( + event: TCEvent + ): Promise>>; + listeners(eventName?: string): Promise> + removeAllListeners(event?: TCEvent): Promise + + + + + balances: TypedContractMethod< + [arg0: AddressLike, ], + [bigint], + 'view' + > + + + + deposit: TypedContractMethod< + [], + [boolean], + 'payable' + > + + + + drain: TypedContractMethod< + [recepient: AddressLike, ], + [void], + 'nonpayable' + > + + + + re: TypedContractMethod< + [], + [string], + 'view' + > + + + + totalBalance: TypedContractMethod< + [], + [bigint], + 'view' + > + + + + withdraw: TypedContractMethod< + [_amount: BigNumberish, ], + [void], + 'nonpayable' + > + + + + getFunction(key: string | FunctionFragment): T; + + getFunction(nameOrSignature: 'balances'): TypedContractMethod< + [arg0: AddressLike, ], + [bigint], + 'view' + >; +getFunction(nameOrSignature: 'deposit'): TypedContractMethod< + [], + [boolean], + 'payable' + >; +getFunction(nameOrSignature: 'drain'): TypedContractMethod< + [recepient: AddressLike, ], + [void], + 'nonpayable' + >; +getFunction(nameOrSignature: 're'): TypedContractMethod< + [], + [string], + 'view' + >; +getFunction(nameOrSignature: 'totalBalance'): TypedContractMethod< + [], + [bigint], + 'view' + >; +getFunction(nameOrSignature: 'withdraw'): TypedContractMethod< + [_amount: BigNumberish, ], + [void], + 'nonpayable' + >; + + getEvent(key: 'depositSuccessful'): TypedContractEvent; + + filters: { + + 'depositSuccessful(string,uint256)': TypedContractEvent; + depositSuccessful: TypedContractEvent; + + }; + } \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/Todo.sol/Todo.ts b/assignments/todo/types/ethers-contracts/Todo.sol/Todo.ts new file mode 100644 index 00000000..fc45ae8e --- /dev/null +++ b/assignments/todo/types/ethers-contracts/Todo.sol/Todo.ts @@ -0,0 +1,104 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { BaseContract, BigNumberish, BytesLike, FunctionFragment, Result, Interface, EventFragment, ContractRunner, ContractMethod, Listener } from "ethers" +import type { TypedContractEvent, TypedDeferredTopicFilter, TypedEventLog, TypedLogDescription, TypedListener, TypedContractMethod } from "../common.js" + + + export interface TodoInterface extends Interface { + getFunction(nameOrSignature: "createTodo" | "markAsDone"): FunctionFragment; + + getEvent(nameOrSignatureOrTopic: "TodoCreated"): EventFragment; + + encodeFunctionData(functionFragment: 'createTodo', values: [string, BigNumberish]): string; +encodeFunctionData(functionFragment: 'markAsDone', values: [BigNumberish]): string; + + decodeFunctionResult(functionFragment: 'createTodo', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'markAsDone', data: BytesLike): Result; + } + + + export namespace TodoCreatedEvent { + export type InputTuple = [text: string, deadline: BigNumberish]; + export type OutputTuple = [text: string, deadline: bigint]; + export interface OutputObject {text: string, deadline: bigint }; + export type Event = TypedContractEvent + export type Filter = TypedDeferredTopicFilter + export type Log = TypedEventLog + export type LogDescription = TypedLogDescription + } + + + + export interface Todo extends BaseContract { + + connect(runner?: ContractRunner | null): Todo; + waitForDeployment(): Promise; + + interface: TodoInterface; + + + queryFilter( + event: TCEvent, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined, + ): Promise>> + queryFilter( + filter: TypedDeferredTopicFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + + on(event: TCEvent, listener: TypedListener): Promise + on(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + once(event: TCEvent, listener: TypedListener): Promise + once(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + listeners( + event: TCEvent + ): Promise>>; + listeners(eventName?: string): Promise> + removeAllListeners(event?: TCEvent): Promise + + + + + createTodo: TypedContractMethod< + [_text: string, _deadline: BigNumberish, ], + [bigint], + 'nonpayable' + > + + + + markAsDone: TypedContractMethod< + [_id: BigNumberish, ], + [void], + 'nonpayable' + > + + + + getFunction(key: string | FunctionFragment): T; + + getFunction(nameOrSignature: 'createTodo'): TypedContractMethod< + [_text: string, _deadline: BigNumberish, ], + [bigint], + 'nonpayable' + >; +getFunction(nameOrSignature: 'markAsDone'): TypedContractMethod< + [_id: BigNumberish, ], + [void], + 'nonpayable' + >; + + getEvent(key: 'TodoCreated'): TypedContractEvent; + + filters: { + + 'TodoCreated(string,uint256)': TypedContractEvent; + TodoCreated: TypedContractEvent; + + }; + } \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/Todo.sol/index.ts b/assignments/todo/types/ethers-contracts/Todo.sol/index.ts new file mode 100644 index 00000000..e33d5e94 --- /dev/null +++ b/assignments/todo/types/ethers-contracts/Todo.sol/index.ts @@ -0,0 +1,5 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +export type { Bank } from './Bank.js'; +export type { Todo } from './Todo.js'; \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/Todo.ts b/assignments/todo/types/ethers-contracts/Todo.ts new file mode 100644 index 00000000..29d04240 --- /dev/null +++ b/assignments/todo/types/ethers-contracts/Todo.ts @@ -0,0 +1,104 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { BaseContract, BigNumberish, BytesLike, FunctionFragment, Result, Interface, EventFragment, ContractRunner, ContractMethod, Listener } from "ethers" +import type { TypedContractEvent, TypedDeferredTopicFilter, TypedEventLog, TypedLogDescription, TypedListener, TypedContractMethod } from "./common.js" + + + export interface TodoInterface extends Interface { + getFunction(nameOrSignature: "createTodo" | "markAsDone"): FunctionFragment; + + getEvent(nameOrSignatureOrTopic: "TodoCreated"): EventFragment; + + encodeFunctionData(functionFragment: 'createTodo', values: [string, BigNumberish]): string; +encodeFunctionData(functionFragment: 'markAsDone', values: [BigNumberish]): string; + + decodeFunctionResult(functionFragment: 'createTodo', data: BytesLike): Result; +decodeFunctionResult(functionFragment: 'markAsDone', data: BytesLike): Result; + } + + + export namespace TodoCreatedEvent { + export type InputTuple = [text: string, deadline: BigNumberish]; + export type OutputTuple = [text: string, deadline: bigint]; + export interface OutputObject {text: string, deadline: bigint }; + export type Event = TypedContractEvent + export type Filter = TypedDeferredTopicFilter + export type Log = TypedEventLog + export type LogDescription = TypedLogDescription + } + + + + export interface Todo extends BaseContract { + + connect(runner?: ContractRunner | null): Todo; + waitForDeployment(): Promise; + + interface: TodoInterface; + + + queryFilter( + event: TCEvent, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined, + ): Promise>> + queryFilter( + filter: TypedDeferredTopicFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>>; + + on(event: TCEvent, listener: TypedListener): Promise + on(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + once(event: TCEvent, listener: TypedListener): Promise + once(filter: TypedDeferredTopicFilter, listener: TypedListener): Promise + + listeners( + event: TCEvent + ): Promise>>; + listeners(eventName?: string): Promise> + removeAllListeners(event?: TCEvent): Promise + + + + + createTodo: TypedContractMethod< + [_text: string, _deadline: BigNumberish, ], + [bigint], + 'nonpayable' + > + + + + markAsDone: TypedContractMethod< + [_id: BigNumberish, ], + [void], + 'nonpayable' + > + + + + getFunction(key: string | FunctionFragment): T; + + getFunction(nameOrSignature: 'createTodo'): TypedContractMethod< + [_text: string, _deadline: BigNumberish, ], + [bigint], + 'nonpayable' + >; +getFunction(nameOrSignature: 'markAsDone'): TypedContractMethod< + [_id: BigNumberish, ], + [void], + 'nonpayable' + >; + + getEvent(key: 'TodoCreated'): TypedContractEvent; + + filters: { + + 'TodoCreated(string,uint256)': TypedContractEvent; + TodoCreated: TypedContractEvent; + + }; + } \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/common.ts b/assignments/todo/types/ethers-contracts/common.ts new file mode 100644 index 00000000..1b4cfcbe --- /dev/null +++ b/assignments/todo/types/ethers-contracts/common.ts @@ -0,0 +1,92 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { + FunctionFragment, + Typed, + EventFragment, + ContractTransaction, + ContractTransactionResponse, + DeferredTopicFilter, + EventLog, + TransactionRequest, + LogDescription, +} from 'ethers' + +export interface TypedDeferredTopicFilter<_TCEvent extends TypedContractEvent> extends DeferredTopicFilter {} + +export interface TypedContractEvent< + InputTuple extends Array = any, + OutputTuple extends Array = any, + OutputObject = any, +> { + (...args: Partial): TypedDeferredTopicFilter> + name: string + fragment: EventFragment + getFragment(...args: Partial): EventFragment +} + +type __TypechainAOutputTuple = T extends TypedContractEvent ? W : never +type __TypechainOutputObject = T extends TypedContractEvent ? V : never + +export interface TypedEventLog extends Omit { + args: __TypechainAOutputTuple & __TypechainOutputObject +} + +export interface TypedLogDescription extends Omit { + args: __TypechainAOutputTuple & __TypechainOutputObject +} + +export type TypedListener = ( + ...listenerArg: [...__TypechainAOutputTuple, TypedEventLog, ...undefined[]] +) => void + +export type MinEthersFactory = { + deploy(...a: ARGS[]): Promise +} + +export type GetContractTypeFromFactory = F extends MinEthersFactory ? C : never +export type GetARGsTypeFromFactory = F extends MinEthersFactory ? Parameters : never + +export type StateMutability = 'nonpayable' | 'payable' | 'view' + +export type BaseOverrides = Omit +export type NonPayableOverrides = Omit +export type PayableOverrides = Omit +export type ViewOverrides = Omit +export type Overrides = S extends 'nonpayable' + ? NonPayableOverrides + : S extends 'payable' + ? PayableOverrides + : ViewOverrides + +export type PostfixOverrides, S extends StateMutability> = A | [...A, Overrides] +export type ContractMethodArgs, S extends StateMutability> = PostfixOverrides< + { [I in keyof A]-?: A[I] | Typed }, + S +> + +export type DefaultReturnType = R extends Array ? R[0] : R + +// export interface ContractMethod = Array, R = any, D extends R | ContractTransactionResponse = R | ContractTransactionResponse> { +export interface TypedContractMethod< + A extends Array = Array, + R = any, + S extends StateMutability = 'payable', +> { + (...args: ContractMethodArgs): S extends 'view' + ? Promise> + : Promise + + name: string + + fragment: FunctionFragment + + getFragment(...args: ContractMethodArgs): FunctionFragment + + populateTransaction(...args: ContractMethodArgs): Promise + staticCall(...args: ContractMethodArgs): Promise> + send(...args: ContractMethodArgs): Promise + estimateGas(...args: ContractMethodArgs): Promise + staticCallResult(...args: ContractMethodArgs): Promise +} diff --git a/assignments/todo/types/ethers-contracts/factories/Bank__factory.ts b/assignments/todo/types/ethers-contracts/factories/Bank__factory.ts new file mode 100644 index 00000000..31e750a8 --- /dev/null +++ b/assignments/todo/types/ethers-contracts/factories/Bank__factory.ts @@ -0,0 +1,175 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { Addressable } from "ethers"; +import { Contract, ContractFactory, ContractTransactionResponse, Interface } from "ethers" +import type { Signer, BigNumberish, ContractDeployTransaction, ContractRunner } from "ethers" +import type { NonPayableOverrides } from "../common.js" + import type { Bank, BankInterface } from "../Bank.js"; + + const _abi = [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_interest", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "sent", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "depositSuccessful", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recepient", + "type": "address" + } + ], + "name": "drain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "re", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] as const; + + const _bytecode = "0x6080604052348015600e575f5ffd5b50604051610513380380610513833981016040819052602b916044565b600155600280546001600160a01b03191633179055605a565b5f602082840312156053575f5ffd5b5051919050565b6104ac806100675f395ff3fe608060405260043610610054575f3560e01c806315d55b281461005857806327e235e3146100775780632e1a7d4d146100b0578063ad7a672f146100d1578063d0e30db0146100e5578063ece53132146100fd575b5f5ffd5b348015610063575f5ffd5b506040513081526020015b60405180910390f35b348015610082575f5ffd5b506100a26100913660046103f2565b60036020525f908152604090205481565b60405190815260200161006e565b3480156100bb575f5ffd5b506100cf6100ca36600461041f565b61011c565b005b3480156100dc575f5ffd5b506100a25f5481565b6100ed610279565b604051901515815260200161006e565b348015610108575f5ffd5b506100cf6101173660046103f2565b610334565b335f908152600360205260409020548111156101745760405162461bcd60e51b8152602060048201526012602482015271496e73756666696369656e742066756e647360701b60448201526064015b60405180910390fd5b804710156101ba5760405162461bcd60e51b8152602060048201526013602482015272436f6e74726163742063616e6e6f742070617960681b604482015260640161016b565b335f90815260036020526040812080548392906101d890849061044a565b9091555050604051600160fd1b81525f90339083906001015f6040518083038185875af1925050503d805f811461022a576040519150601f19603f3d011682016040523d82523d5f602084013e61022f565b606091505b50509050806102755760405162461bcd60e51b81526020600482015260126024820152711d1c985b9cd8d85d1a5bdb8819985a5b195960721b604482015260640161016b565b5050565b5f5f34116102bf5760405162461bcd60e51b815260206004820152601360248201527243616e6e6f74206465706f736974205a65726f60681b604482015260640161016b565b335f90815260036020526040812080543492906102dd908490610463565b9091555050604080518181526004818301526314d95b9d60e21b606082015234602082015290517f11579e59ce4f784f9c9df4fc8c5190ea28474957cd630fc5e6c00e5d8e7e8e279181900360800190a150600190565b6002546001600160a01b0316331461034a575f5ffd5b604051600160fd1b815247905f906001600160a01b0384169083906001015f6040518083038185875af1925050503d805f81146103a2576040519150601f19603f3d011682016040523d82523d5f602084013e6103a7565b606091505b50509050806103ed5760405162461bcd60e51b81526020600482015260126024820152711d1c985b9cd8d85d1a5bdb8819985a5b195960721b604482015260640161016b565b505050565b5f60208284031215610402575f5ffd5b81356001600160a01b0381168114610418575f5ffd5b9392505050565b5f6020828403121561042f575f5ffd5b5035919050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561045d5761045d610436565b92915050565b8082018082111561045d5761045d61043656fea2646970667358221220eb63aaadabd4a2b7dd49e541112daf9f75f1648f4332c358e13b54292edd889664736f6c634300081c0033"; + + + type BankConstructorParams = [signer?: Signer] | ConstructorParameters; + + const isSuperArgs = (xs: BankConstructorParams): xs is ConstructorParameters => + xs.length > 1 + + + export class Bank__factory extends ContractFactory { + + constructor(...args: BankConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + + } + + override getDeployTransaction(_interest: BigNumberish, overrides?: NonPayableOverrides & { from?: string }): Promise { + return super.getDeployTransaction(_interest, overrides || {}); + }; + override deploy(_interest: BigNumberish, overrides?: NonPayableOverrides & { from?: string }) { + return super.deploy(_interest, overrides || {}) as Promise; + } + override connect(runner: ContractRunner | null): Bank__factory { + return super.connect(runner) as Bank__factory; + } + + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): BankInterface { + return new Interface(_abi) as BankInterface; + } + + override attach(address: string | Addressable): Bank { + return super.attach(address) as Bank; + } + static connect(address: string, runner?: ContractRunner | null): Bank { + return new Contract(address, _abi, runner) as unknown as Bank; + } + } + + + \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/factories/Counter__factory.ts b/assignments/todo/types/ethers-contracts/factories/Counter__factory.ts new file mode 100644 index 00000000..00caab04 --- /dev/null +++ b/assignments/todo/types/ethers-contracts/factories/Counter__factory.ts @@ -0,0 +1,107 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { Addressable } from "ethers"; +import { Contract, ContractFactory, ContractTransactionResponse, Interface } from "ethers" +import type { Signer, ContractDeployTransaction, ContractRunner } from "ethers" +import type { NonPayableOverrides } from "../common.js" + import type { Counter, CounterInterface } from "../Counter.js"; + + const _abi = [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "by", + "type": "uint256" + } + ], + "name": "Increment", + "type": "event" + }, + { + "inputs": [], + "name": "inc", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "by", + "type": "uint256" + } + ], + "name": "incBy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "x", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] as const; + + const _bytecode = "0x6080604052348015600e575f5ffd5b506103cf8061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80630c55699c14610043578063371303c01461006157806370119d061461006b575b5f5ffd5b61004b610087565b6040516100589190610187565b60405180910390f35b61006961008c565b005b610085600480360381019061008091906101ce565b6100dc565b005b5f5481565b5f5f81548092919061009d90610226565b91905055507f51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a8160016040516100d291906102af565b60405180910390a1565b5f811161011e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161011590610348565b60405180910390fd5b805f5f82825461012e9190610366565b925050819055507f51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81816040516101649190610187565b60405180910390a150565b5f819050919050565b6101818161016f565b82525050565b5f60208201905061019a5f830184610178565b92915050565b5f5ffd5b6101ad8161016f565b81146101b7575f5ffd5b50565b5f813590506101c8816101a4565b92915050565b5f602082840312156101e3576101e26101a0565b5b5f6101f0848285016101ba565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6102308261016f565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610262576102616101f9565b5b600182019050919050565b5f819050919050565b5f819050919050565b5f61029961029461028f8461026d565b610276565b61016f565b9050919050565b6102a98161027f565b82525050565b5f6020820190506102c25f8301846102a0565b92915050565b5f82825260208201905092915050565b7f696e6342793a20696e6372656d656e742073686f756c6420626520706f7369745f8201527f6976650000000000000000000000000000000000000000000000000000000000602082015250565b5f6103326023836102c8565b915061033d826102d8565b604082019050919050565b5f6020820190508181035f83015261035f81610326565b9050919050565b5f6103708261016f565b915061037b8361016f565b9250828201905080821115610393576103926101f9565b5b9291505056fea26469706673582212208964bf78f883ff62c92c3c09416a09fa5a731da0068f08bc3384c0fdbe22f74f64736f6c634300081c0033"; + + + type CounterConstructorParams = [signer?: Signer] | ConstructorParameters; + + const isSuperArgs = (xs: CounterConstructorParams): xs is ConstructorParameters => + xs.length > 1 + + + export class Counter__factory extends ContractFactory { + + constructor(...args: CounterConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + + } + + override getDeployTransaction(overrides?: NonPayableOverrides & { from?: string }): Promise { + return super.getDeployTransaction(overrides || {}); + }; + override deploy(overrides?: NonPayableOverrides & { from?: string }) { + return super.deploy(overrides || {}) as Promise; + } + override connect(runner: ContractRunner | null): Counter__factory { + return super.connect(runner) as Counter__factory; + } + + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): CounterInterface { + return new Interface(_abi) as CounterInterface; + } + + override attach(address: string | Addressable): Counter { + return super.attach(address) as Counter; + } + static connect(address: string, runner?: ContractRunner | null): Counter { + return new Contract(address, _abi, runner) as unknown as Counter; + } + } + + + \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/factories/Todo.sol/Bank__factory.ts b/assignments/todo/types/ethers-contracts/factories/Todo.sol/Bank__factory.ts new file mode 100644 index 00000000..faf376c7 --- /dev/null +++ b/assignments/todo/types/ethers-contracts/factories/Todo.sol/Bank__factory.ts @@ -0,0 +1,175 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { Addressable } from "ethers"; +import { Contract, ContractFactory, ContractTransactionResponse, Interface } from "ethers" +import type { Signer, BigNumberish, ContractDeployTransaction, ContractRunner } from "ethers" +import type { NonPayableOverrides } from "../../common.js" + import type { Bank, BankInterface } from "../../Todo.sol/Bank.js"; + + const _abi = [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_interest", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "sent", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "depositSuccessful", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deposit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recepient", + "type": "address" + } + ], + "name": "drain", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "re", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] as const; + + const _bytecode = "0x6080604052348015600e575f5ffd5b50604051610ab6380380610ab68339818101604052810190602e919060ac565b806001819055503360025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505060d2565b5f5ffd5b5f819050919050565b608e81607e565b81146097575f5ffd5b50565b5f8151905060a6816087565b92915050565b5f6020828403121560be5760bd607a565b5b5f60c984828501609a565b91505092915050565b6109d7806100df5f395ff3fe608060405260043610610054575f3560e01c806315d55b281461005857806327e235e3146100825780632e1a7d4d146100be578063ad7a672f146100e6578063d0e30db014610110578063ece531321461012e575b5f5ffd5b348015610063575f5ffd5b5061006c610156565b6040516100799190610555565b60405180910390f35b34801561008d575f5ffd5b506100a860048036038101906100a3919061059c565b61015d565b6040516100b591906105df565b60405180910390f35b3480156100c9575f5ffd5b506100e460048036038101906100df9190610622565b610172565b005b3480156100f1575f5ffd5b506100fa610334565b60405161010791906105df565b60405180910390f35b610118610339565b6040516101259190610667565b60405180910390f35b348015610139575f5ffd5b50610154600480360381019061014f919061059c565b61040d565b005b5f30905090565b6003602052805f5260405f205f915090505481565b8060035f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156101f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101e9906106da565b60405180910390fd5b80471015610235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161022c90610742565b60405180910390fd5b8060035f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254610281919061078d565b925050819055505f3373ffffffffffffffffffffffffffffffffffffffff16826040516102ad90610814565b5f6040518083038185875af1925050503d805f81146102e7576040519150601f19603f3d011682016040523d82523d5f602084013e6102ec565b606091505b5050905080610330576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032790610872565b60405180910390fd5b5050565b5f5481565b5f5f341161037c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610373906108da565b60405180910390fd5b3460035f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546103c891906108f8565b925050819055507f11579e59ce4f784f9c9df4fc8c5190ea28474957cd630fc5e6c00e5d8e7e8e27346040516103fe9190610975565b60405180910390a16001905090565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610465575f5ffd5b5f4790505f8273ffffffffffffffffffffffffffffffffffffffff168260405161048e90610814565b5f6040518083038185875af1925050503d805f81146104c8576040519150601f19603f3d011682016040523d82523d5f602084013e6104cd565b606091505b5050905080610511576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161050890610872565b60405180910390fd5b505050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61053f82610516565b9050919050565b61054f81610535565b82525050565b5f6020820190506105685f830184610546565b92915050565b5f5ffd5b61057b81610535565b8114610585575f5ffd5b50565b5f8135905061059681610572565b92915050565b5f602082840312156105b1576105b061056e565b5b5f6105be84828501610588565b91505092915050565b5f819050919050565b6105d9816105c7565b82525050565b5f6020820190506105f25f8301846105d0565b92915050565b610601816105c7565b811461060b575f5ffd5b50565b5f8135905061061c816105f8565b92915050565b5f602082840312156106375761063661056e565b5b5f6106448482850161060e565b91505092915050565b5f8115159050919050565b6106618161064d565b82525050565b5f60208201905061067a5f830184610658565b92915050565b5f82825260208201905092915050565b7f496e73756666696369656e742066756e647300000000000000000000000000005f82015250565b5f6106c4601283610680565b91506106cf82610690565b602082019050919050565b5f6020820190508181035f8301526106f1816106b8565b9050919050565b7f436f6e74726163742063616e6e6f7420706179000000000000000000000000005f82015250565b5f61072c601383610680565b9150610737826106f8565b602082019050919050565b5f6020820190508181035f83015261075981610720565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610797826105c7565b91506107a2836105c7565b92508282039050818111156107ba576107b9610760565b5b92915050565b5f81905092915050565b7f20000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6107fe6001836107c0565b9150610809826107ca565b600182019050919050565b5f61081e826107f2565b9150819050919050565b7f7472616e73636174696f6e206661696c656400000000000000000000000000005f82015250565b5f61085c601283610680565b915061086782610828565b602082019050919050565b5f6020820190508181035f83015261088981610850565b9050919050565b7f43616e6e6f74206465706f736974205a65726f000000000000000000000000005f82015250565b5f6108c4601383610680565b91506108cf82610890565b602082019050919050565b5f6020820190508181035f8301526108f1816108b8565b9050919050565b5f610902826105c7565b915061090d836105c7565b925082820190508082111561092557610924610760565b5b92915050565b7f53656e74000000000000000000000000000000000000000000000000000000005f82015250565b5f61095f600483610680565b915061096a8261092b565b602082019050919050565b5f6040820190508181035f83015261098c81610953565b905061099b60208301846105d0565b9291505056fea26469706673582212203074da2016f71672c4a3c18d0eb649acd6a4b189e40b8a7db7be8c159fd83ea364736f6c634300081c0033"; + + + type BankConstructorParams = [signer?: Signer] | ConstructorParameters; + + const isSuperArgs = (xs: BankConstructorParams): xs is ConstructorParameters => + xs.length > 1 + + + export class Bank__factory extends ContractFactory { + + constructor(...args: BankConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + + } + + override getDeployTransaction(_interest: BigNumberish, overrides?: NonPayableOverrides & { from?: string }): Promise { + return super.getDeployTransaction(_interest, overrides || {}); + }; + override deploy(_interest: BigNumberish, overrides?: NonPayableOverrides & { from?: string }) { + return super.deploy(_interest, overrides || {}) as Promise; + } + override connect(runner: ContractRunner | null): Bank__factory { + return super.connect(runner) as Bank__factory; + } + + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): BankInterface { + return new Interface(_abi) as BankInterface; + } + + override attach(address: string | Addressable): Bank { + return super.attach(address) as Bank; + } + static connect(address: string, runner?: ContractRunner | null): Bank { + return new Contract(address, _abi, runner) as unknown as Bank; + } + } + + + \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/factories/Todo.sol/Todo__factory.ts b/assignments/todo/types/ethers-contracts/factories/Todo.sol/Todo__factory.ts new file mode 100644 index 00000000..96e032a2 --- /dev/null +++ b/assignments/todo/types/ethers-contracts/factories/Todo.sol/Todo__factory.ts @@ -0,0 +1,117 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { Addressable } from "ethers"; +import { Contract, ContractFactory, ContractTransactionResponse, Interface } from "ethers" +import type { Signer, ContractDeployTransaction, ContractRunner } from "ethers" +import type { NonPayableOverrides } from "../../common.js" + import type { Todo, TodoInterface } from "../../Todo.sol/Todo.js"; + + const _abi = [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "text", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "TodoCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_text", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + } + ], + "name": "createTodo", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_id", + "type": "uint256" + } + ], + "name": "markAsDone", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] as const; + + const _bytecode = "0x6080604052348015600e575f5ffd5b50610db98061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063d74de14d14610038578063ece28c6c14610054575b5f5ffd5b610052600480360381019061004d91906104fc565b610084565b005b61006e60048036038101906100699190610663565b61025c565b60405161007b91906106cc565b60405180910390f35b5f8111801561009457505f548111155b6100d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100ca9061073f565b60405180910390fd5b5f60015f8381526020019081526020015f2090505f60038111156100fa576100f961075d565b5b816003015f9054906101000a900460ff16600381111561011d5761011c61075d565b5b1461015d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610154906107d4565b60405180910390fd5b806001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101e59061083c565b60405180910390fd5b806004015442111561022b576003816003015f6101000a81548160ff021916908360038111156102215761022061075d565b5b0217905550610258565b6001816003015f6101000a81548160ff021916908360038111156102525761025161075d565b5b02179055505b5050565b5f5f8351116102a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610297906108a4565b60405180910390fd5b610258426102ae91906108ef565b82116102ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102e69061096c565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff160361035d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610354906109d4565b60405180910390fd5b5f5f81548092919061036e906109f2565b91905055506040518060a001604052805f5481526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018481526020015f60038111156103ba576103b961075d565b5b81526020018381525060015f5f5481526020019081526020015f205f820151815f01556020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020190816104389190610c40565b506060820151816003015f6101000a81548160ff021916908360038111156104635761046261075d565b5b0217905550608082015181600401559050507f022c3fffe570decf2328dbf4f2af598df5112da7e31568af8b927c48276ccae383836040516104a6929190610d55565b60405180910390a15f54905092915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f819050919050565b6104db816104c9565b81146104e5575f5ffd5b50565b5f813590506104f6816104d2565b92915050565b5f60208284031215610511576105106104c1565b5b5f61051e848285016104e8565b91505092915050565b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6105758261052f565b810181811067ffffffffffffffff821117156105945761059361053f565b5b80604052505050565b5f6105a66104b8565b90506105b2828261056c565b919050565b5f67ffffffffffffffff8211156105d1576105d061053f565b5b6105da8261052f565b9050602081019050919050565b828183375f83830152505050565b5f610607610602846105b7565b61059d565b9050828152602081018484840111156106235761062261052b565b5b61062e8482856105e7565b509392505050565b5f82601f83011261064a57610649610527565b5b813561065a8482602086016105f5565b91505092915050565b5f5f60408385031215610679576106786104c1565b5b5f83013567ffffffffffffffff811115610696576106956104c5565b5b6106a285828601610636565b92505060206106b3858286016104e8565b9150509250929050565b6106c6816104c9565b82525050565b5f6020820190506106df5f8301846106bd565b92915050565b5f82825260208201905092915050565b7f696e76616c6964206964000000000000000000000000000000000000000000005f82015250565b5f610729600a836106e5565b9150610734826106f5565b602082019050919050565b5f6020820190508181035f8301526107568161071d565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b7f4e6f742070656e64696e670000000000000000000000000000000000000000005f82015250565b5f6107be600b836106e5565b91506107c98261078a565b602082019050919050565b5f6020820190508181035f8301526107eb816107b2565b9050919050565b7f756e617574686f72697a65642043616c6c6572000000000000000000000000005f82015250565b5f6108266013836106e5565b9150610831826107f2565b602082019050919050565b5f6020820190508181035f8301526108538161081a565b9050919050565b7f456d7074792074657874000000000000000000000000000000000000000000005f82015250565b5f61088e600a836106e5565b91506108998261085a565b602082019050919050565b5f6020820190508181035f8301526108bb81610882565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6108f9826104c9565b9150610904836104c9565b925082820190508082111561091c5761091b6108c2565b5b92915050565b7f496e76616c696420646561646c696e65000000000000000000000000000000005f82015250565b5f6109566010836106e5565b915061096182610922565b602082019050919050565b5f6020820190508181035f8301526109838161094a565b9050919050565b7f5a65726f206164647265737300000000000000000000000000000000000000005f82015250565b5f6109be600c836106e5565b91506109c98261098a565b602082019050919050565b5f6020820190508181035f8301526109eb816109b2565b9050919050565b5f6109fc826104c9565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610a2e57610a2d6108c2565b5b600182019050919050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610a8757607f821691505b602082108103610a9a57610a99610a43565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f60088302610afc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82610ac1565b610b068683610ac1565b95508019841693508086168417925050509392505050565b5f819050919050565b5f610b41610b3c610b37846104c9565b610b1e565b6104c9565b9050919050565b5f819050919050565b610b5a83610b27565b610b6e610b6682610b48565b848454610acd565b825550505050565b5f5f905090565b610b85610b76565b610b90818484610b51565b505050565b5b81811015610bb357610ba85f82610b7d565b600181019050610b96565b5050565b601f821115610bf857610bc981610aa0565b610bd284610ab2565b81016020851015610be1578190505b610bf5610bed85610ab2565b830182610b95565b50505b505050565b5f82821c905092915050565b5f610c185f1984600802610bfd565b1980831691505092915050565b5f610c308383610c09565b9150826002028217905092915050565b610c4982610a39565b67ffffffffffffffff811115610c6257610c6161053f565b5b610c6c8254610a70565b610c77828285610bb7565b5f60209050601f831160018114610ca8575f8415610c96578287015190505b610ca08582610c25565b865550610d07565b601f198416610cb686610aa0565b5f5b82811015610cdd57848901518255600182019150602085019450602081019050610cb8565b86831015610cfa5784890151610cf6601f891682610c09565b8355505b6001600288020188555050505b505050505050565b8281835e5f83830152505050565b5f610d2782610a39565b610d3181856106e5565b9350610d41818560208601610d0f565b610d4a8161052f565b840191505092915050565b5f6040820190508181035f830152610d6d8185610d1d565b9050610d7c60208301846106bd565b939250505056fea264697066735822122022acaaf639e5b9f45398a055446dfe72293eab2e240d69b44300a75c4bfaf39864736f6c634300081c0033"; + + + type TodoConstructorParams = [signer?: Signer] | ConstructorParameters; + + const isSuperArgs = (xs: TodoConstructorParams): xs is ConstructorParameters => + xs.length > 1 + + + export class Todo__factory extends ContractFactory { + + constructor(...args: TodoConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + + } + + override getDeployTransaction(overrides?: NonPayableOverrides & { from?: string }): Promise { + return super.getDeployTransaction(overrides || {}); + }; + override deploy(overrides?: NonPayableOverrides & { from?: string }) { + return super.deploy(overrides || {}) as Promise; + } + override connect(runner: ContractRunner | null): Todo__factory { + return super.connect(runner) as Todo__factory; + } + + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): TodoInterface { + return new Interface(_abi) as TodoInterface; + } + + override attach(address: string | Addressable): Todo { + return super.attach(address) as Todo; + } + static connect(address: string, runner?: ContractRunner | null): Todo { + return new Contract(address, _abi, runner) as unknown as Todo; + } + } + + + \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/factories/Todo.sol/index.ts b/assignments/todo/types/ethers-contracts/factories/Todo.sol/index.ts new file mode 100644 index 00000000..5a17b260 --- /dev/null +++ b/assignments/todo/types/ethers-contracts/factories/Todo.sol/index.ts @@ -0,0 +1,5 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +export { Bank__factory } from './Bank__factory.js'; +export { Todo__factory } from './Todo__factory.js'; \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/factories/Todo__factory.ts b/assignments/todo/types/ethers-contracts/factories/Todo__factory.ts new file mode 100644 index 00000000..c8838a6d --- /dev/null +++ b/assignments/todo/types/ethers-contracts/factories/Todo__factory.ts @@ -0,0 +1,117 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { Addressable } from "ethers"; +import { Contract, ContractFactory, ContractTransactionResponse, Interface } from "ethers" +import type { Signer, ContractDeployTransaction, ContractRunner } from "ethers" +import type { NonPayableOverrides } from "../common.js" + import type { Todo, TodoInterface } from "../Todo.js"; + + const _abi = [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "text", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + } + ], + "name": "TodoCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_text", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_deadline", + "type": "uint256" + } + ], + "name": "createTodo", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_id", + "type": "uint256" + } + ], + "name": "markAsDone", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] as const; + + const _bytecode = "0x6080604052348015600e575f5ffd5b506106568061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063d74de14d14610038578063ece28c6c1461004d575b5f5ffd5b61004b610046366004610372565b610072565b005b61006061005b36600461039d565b6101a4565b60405190815260200160405180910390f35b5f8111801561008257505f548111155b6100c05760405162461bcd60e51b815260206004820152600a6024820152691a5b9d985b1a59081a5960b21b60448201526064015b60405180910390fd5b5f8181526001602052604081209060038083015460ff16908111156100e7576100e7610452565b146101225760405162461bcd60e51b815260206004820152600b60248201526a4e6f742070656e64696e6760a81b60448201526064016100b7565b60018101546001600160a01b031633146101745760405162461bcd60e51b81526020600482015260136024820152723ab730baba3437b934bd32b21021b0b63632b960691b60448201526064016100b7565b8060040154421115610193576003908101805460ff1916909117905550565b600301805460ff1916600117905550565b5f5f8351116101e25760405162461bcd60e51b815260206004820152600a602482015269115b5c1d1e481d195e1d60b21b60448201526064016100b7565b6101ee4261025861047a565b821161022f5760405162461bcd60e51b815260206004820152601060248201526f496e76616c696420646561646c696e6560801b60448201526064016100b7565b3361026b5760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b60448201526064016100b7565b5f805490806102798361048d565b90915550506040805160a0810182525f80548252336020830152918101859052906060820190815260209081018490525f805481526001808352604091829020845181559284015190830180546001600160a01b0319166001600160a01b0390921691909117905582015160028201906102f39082610529565b506060820151816003015f6101000a81548160ff0219169083600381111561031d5761031d610452565b0217905550608082015181600401559050507f022c3fffe570decf2328dbf4f2af598df5112da7e31568af8b927c48276ccae383836040516103609291906105e4565b60405180910390a1505f545b92915050565b5f60208284031215610382575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156103ae575f5ffd5b823567ffffffffffffffff8111156103c4575f5ffd5b8301601f810185136103d4575f5ffd5b803567ffffffffffffffff8111156103ee576103ee610389565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561041d5761041d610389565b604052818152828201602001871015610434575f5ffd5b816020840160208301375f6020928201830152969401359450505050565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561036c5761036c610466565b5f6001820161049e5761049e610466565b5060010190565b600181811c908216806104b957607f821691505b6020821081036104d757634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561052457805f5260205f20601f840160051c810160208510156105025750805b601f840160051c820191505b81811015610521575f815560010161050e565b50505b505050565b815167ffffffffffffffff81111561054357610543610389565b6105578161055184546104a5565b846104dd565b6020601f821160018114610589575f83156105725750848201515b5f19600385901b1c1916600184901b178455610521565b5f84815260208120601f198516915b828110156105b85787850151825560209485019460019092019101610598565b50848210156105d557868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b604081525f83518060408401528060208601606085015e5f606082850101526060601f19601f830116840101915050826020830152939250505056fea264697066735822122058a230f22781a7908f9b744117232535d23a25fa1216e8526855770e6f935e6364736f6c634300081c0033"; + + + type TodoConstructorParams = [signer?: Signer] | ConstructorParameters; + + const isSuperArgs = (xs: TodoConstructorParams): xs is ConstructorParameters => + xs.length > 1 + + + export class Todo__factory extends ContractFactory { + + constructor(...args: TodoConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + + } + + override getDeployTransaction(overrides?: NonPayableOverrides & { from?: string }): Promise { + return super.getDeployTransaction(overrides || {}); + }; + override deploy(overrides?: NonPayableOverrides & { from?: string }) { + return super.deploy(overrides || {}) as Promise; + } + override connect(runner: ContractRunner | null): Todo__factory { + return super.connect(runner) as Todo__factory; + } + + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): TodoInterface { + return new Interface(_abi) as TodoInterface; + } + + override attach(address: string | Addressable): Todo { + return super.attach(address) as Todo; + } + static connect(address: string, runner?: ContractRunner | null): Todo { + return new Contract(address, _abi, runner) as unknown as Todo; + } + } + + + \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/factories/index.ts b/assignments/todo/types/ethers-contracts/factories/index.ts new file mode 100644 index 00000000..5a17b260 --- /dev/null +++ b/assignments/todo/types/ethers-contracts/factories/index.ts @@ -0,0 +1,5 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +export { Bank__factory } from './Bank__factory.js'; +export { Todo__factory } from './Todo__factory.js'; \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/hardhat.d.ts b/assignments/todo/types/ethers-contracts/hardhat.d.ts new file mode 100644 index 00000000..256d2b9e --- /dev/null +++ b/assignments/todo/types/ethers-contracts/hardhat.d.ts @@ -0,0 +1,51 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ + + +import { ethers } from 'ethers' +import { DeployContractOptions, FactoryOptions, HardhatEthersHelpers as HardhatEthersHelpersBase} from "@nomicfoundation/hardhat-ethers/types"; + +import * as Contracts from "./index.js"; + +declare module "@nomicfoundation/hardhat-ethers/types" { + interface HardhatEthersHelpers extends HardhatEthersHelpersBase { + getContractFactory(name: 'Bank', signerOrOptions?: ethers.Signer | FactoryOptions): Promise +getContractFactory(name: 'Todo', signerOrOptions?: ethers.Signer | FactoryOptions): Promise + + getContractAt(name: 'Bank', address: string | ethers.Addressable, signer?: ethers.Signer): Promise +getContractAt(name: 'Todo', address: string | ethers.Addressable, signer?: ethers.Signer): Promise + + deployContract(name: 'Bank', signerOrOptions?: ethers.Signer | DeployContractOptions): Promise +deployContract(name: 'Todo', signerOrOptions?: ethers.Signer | DeployContractOptions): Promise + + deployContract(name: 'Bank', args: any[], signerOrOptions?: ethers.Signer | DeployContractOptions): Promise +deployContract(name: 'Todo', args: any[], signerOrOptions?: ethers.Signer | DeployContractOptions): Promise + + // default types + getContractFactory( + name: string, + signerOrOptions?: ethers.Signer | FactoryOptions + ): Promise; + getContractFactory( + abi: any[], + bytecode: ethers.BytesLike, + signer?: ethers.Signer + ): Promise; + getContractAt( + nameOrAbi: string | any[], + address: string | ethers.Addressable, + signer?: ethers.Signer + ): Promise; + deployContract( + name: string, + signerOrOptions?: ethers.Signer | DeployContractOptions + ): Promise; + deployContract( + name: string, + args: any[], + signerOrOptions?: ethers.Signer | DeployContractOptions + ): Promise; + } +} + \ No newline at end of file diff --git a/assignments/todo/types/ethers-contracts/index.ts b/assignments/todo/types/ethers-contracts/index.ts new file mode 100644 index 00000000..efbe68bd --- /dev/null +++ b/assignments/todo/types/ethers-contracts/index.ts @@ -0,0 +1,8 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +export type { Bank } from './Bank.js'; +export type { Todo } from './Todo.js'; +export * as factories from './factories/index.js'; +export { Bank__factory } from './factories/Bank__factory.js'; +export { Todo__factory } from './factories/Todo__factory.js'; \ No newline at end of file diff --git a/sessions/intro-to-testing/test/TimelockV1.ts b/sessions/intro-to-testing/test/TimelockV1.ts index 30ed7f25..8ca50e27 100644 --- a/sessions/intro-to-testing/test/TimelockV1.ts +++ b/sessions/intro-to-testing/test/TimelockV1.ts @@ -40,6 +40,7 @@ describe('TimelockV1 Test Suite', () => { beforeEach(async () => { TimelockV1 = await ethers.deployContract('TimeLockV1'); [addr1, addr2] = await ethers.getSigners(); + amount = toWei('1'); }); describe('Deployment', () => { @@ -135,3 +136,120 @@ describe('TimelockV1 Test Suite', () => { }); }); }); + +describe('Withdraw Transaction', () => { + describe('Validations', () => { + it('should revert when vault ID is invalid', async () => { + await expect( + TimelockV1.connect(addr1).withdraw(0) + ).to.be.revertedWith('Invalid vault ID'); + }); + + it('should revert when vault is not active', async () => { + const currentTime = (await ethers.provider.getBlock('latest'))!.timestamp; + const unlockTime = currentTime + 100; + await TimelockV1.connect(addr1).deposit(unlockTime, { value: toWei('1') }); + + await ethers.provider.send('evm_increaseTime', [100]); + await ethers.provider.send('evm_mine', []); + + await TimelockV1.connect(addr1).withdraw(0); + + await expect( + TimelockV1.connect(addr1).withdraw(0) + ).to.be.revertedWith('Vault is not active'); + }); + + it('should revert when funds are still locked', async () => { + const unlockTime = (await ethers.provider.getBlock('latest'))!.timestamp + 3600; + await TimelockV1.connect(addr1).deposit(unlockTime, { value: toWei('1') }); + + await expect( + TimelockV1.connect(addr1).withdraw(0) + ).to.be.revertedWith('Funds are still locked'); + }); + + it('should revert when vault has zero balance', async () => { + const currentTime = (await ethers.provider.getBlock('latest'))!.timestamp; + const unlockTime = currentTime + 100; + await TimelockV1.connect(addr1).deposit(unlockTime, { value: toWei('1') }); + + await ethers.provider.send('evm_increaseTime', [100]); + await ethers.provider.send('evm_mine', []); + + await TimelockV1.connect(addr1).withdraw(0); + + await expect( + TimelockV1.connect(addr1).withdraw(0) + ).to.be.revertedWith('Vault is not active'); + }); + }); + + describe('Success Cases', () => { + it('should withdraw funds and emit Withdrawn event', async () => { + const currentTime = (await ethers.provider.getBlock('latest'))!.timestamp; + const unlockTime = currentTime + 100; + await TimelockV1.connect(addr1).deposit(unlockTime, { value: amount }); + + await ethers.provider.send('evm_increaseTime', [100]); + await ethers.provider.send('evm_mine', []); + + await expect(TimelockV1.connect(addr1).withdraw(0)) + .to.emit(TimelockV1, 'Withdrawn') + .withArgs(addr1.address, 0, amount); + }); + + it('should transfer correct amount to user', async () => { + const currentTime = (await ethers.provider.getBlock('latest'))!.timestamp; + const unlockTime = currentTime + 100; + const amount = toWei('1'); + await TimelockV1.connect(addr1).deposit(unlockTime, { value: amount }); + + await ethers.provider.send('evm_increaseTime', [100]); + await ethers.provider.send('evm_mine', []); + + const balanceBefore = await ethers.provider.getBalance(addr1.address); + const tx = await TimelockV1.connect(addr1).withdraw(0); + const receipt = await tx.wait(); + const gasCost = receipt.gasUsed * receipt.gasPrice; + const balanceAfter = await ethers.provider.getBalance(addr1.address); + + expect(balanceAfter).to.equal(balanceBefore + amount - BigInt(gasCost)); + }); + + it('should mark vault as inactive and clear balance', async () => { + const currentTime = (await ethers.provider.getBlock('latest'))!.timestamp; + const unlockTime = currentTime + 100; + await TimelockV1.connect(addr1).deposit(unlockTime, { value: toWei('1') }); + + await ethers.provider.send('evm_increaseTime', [100]); + await ethers.provider.send('evm_mine', []); + + await TimelockV1.connect(addr1).withdraw(0); + + const vault = await TimelockV1.getVault(addr1.address, 0); + expect(vault.balance).to.equal(0); + expect(vault.active).to.be.false; + }); + + it('should allow withdrawing from specific vault when multiple exist', async () => { + const currentTime = (await ethers.provider.getBlock('latest'))!.timestamp; + const unlockTime1 = currentTime + 100; + const unlockTime2 = currentTime + 7200; + + await TimelockV1.connect(addr1).deposit(unlockTime1, { value: toWei('1') }); + await TimelockV1.connect(addr1).deposit(unlockTime2, { value: toWei('2') }); + + await ethers.provider.send('evm_increaseTime', [100]); + await ethers.provider.send('evm_mine', []); + + await TimelockV1.connect(addr1).withdraw(0); + + const vault0 = await TimelockV1.getVault(addr1.address, 0); + const vault1 = await TimelockV1.getVault(addr1.address, 1); + + expect(vault0.active).to.be.false; + expect(vault1.active).to.be.true; + }); + }); + });