mirror of
https://github.com/luxfi/evm.git
synced 2026-09-24 00:27:44 +00:00
* add equality tests * regenerate abis * add extra padding tests * override network upgrades (#839) * override network upgrades * genesis network upgrades defaults * fix conflicts * Update plugin/evm/vm.go * update native minter * nativeminter nit test changes * replace fee manager packers * remove generated abis * Update precompile/contracts/feemanager/contract.go Co-authored-by: Darioush Jalali <[email protected]> Signed-off-by: Ceyhun Onur <[email protected]> * fix comments * add event packing/unpacking to contract template * add pack event tests to template * add event precompile bind tests * nits * separate event file * Update accounts/abi/bind/precompilebind/precompile_bind.go Co-authored-by: aaronbuchwald <[email protected]> Signed-off-by: Ceyhun Onur <[email protected]> * revert set changes * change event comments * wip: log allow list events * propagated allow list events to other precompiles * add get event gas cost and tests * nits * revert unrelated changes * add allowlist events * add topics to GetLogData * fix dep cycle in tests * add allowlist hardhat tests * use len in zero assertion Signed-off-by: Ceyhun Onur <[email protected]> * Update test_allowlist.go Signed-off-by: Ceyhun Onur <[email protected]> * add sender to indexed topics * Update utils.go Signed-off-by: Ceyhun Onur <[email protected]> * add output names * add signature topic gas costs * Update precompile/testutils/test_precompile.go Co-authored-by: Darioush Jalali <[email protected]> Signed-off-by: Ceyhun Onur <[email protected]> * Update accounts/abi/bind/precompilebind/precompile_event_template.go Co-authored-by: Darioush Jalali <[email protected]> Signed-off-by: Ceyhun Onur <[email protected]> * fix tests * fix tests * return err * add RoleSet event * Update contracts/test/contract_deployer_allow_list.ts Co-authored-by: Darioush Jalali <[email protected]> Signed-off-by: Ceyhun Onur <[email protected]> * Update contracts/test/tx_allow_list.ts Co-authored-by: Darioush Jalali <[email protected]> Signed-off-by: Ceyhun Onur <[email protected]> * add assert event func * use hash len --------- Signed-off-by: Ceyhun Onur <[email protected]> Signed-off-by: Ceyhun Onur <[email protected]> Co-authored-by: Ceyhun Onur <[email protected]> Co-authored-by: Darioush Jalali <[email protected]> Co-authored-by: aaronbuchwald <[email protected]>
135 lines
6.6 KiB
TypeScript
135 lines
6.6 KiB
TypeScript
import { ethers } from "hardhat"
|
|
import { CallOverrides } from "ethers"
|
|
import assert from "assert"
|
|
|
|
/*
|
|
*
|
|
* The `test` function is a wrapper around Mocha's `it` function. It provides a normalized framework for running the
|
|
* majority of your test assertions inside of a smart-contract, using `DS-Test`.
|
|
* The API can be used as follows (all of the examples are equivalent):
|
|
* ```ts
|
|
* test("<test_name>", "<contract_function_name>")
|
|
* test("<test_name>", ["<contract_function_name>"])
|
|
* test("<test_name>", { method: "<contract_function_name>", overrides: {}, shouldFail: false, debug: false })
|
|
* test("<test_name>", [{ method: "<contract_function_name>", overrides: {}, shouldFail: false, debug: false }])
|
|
* test("<test_name>", [{ method: "<contract_function_name>", shouldFail: false, debug: false }], {})
|
|
* ```
|
|
* Many contract functions can be called as a part of the same test:
|
|
* ```ts
|
|
* test("<test_name>", ["<step_fn1>", "<step_fn2>", "<step_fn3>"])
|
|
* ```
|
|
* Individual test functions can describe their own overrides with the `overrides` property.
|
|
* If an object is passed in as the third argument to `test`, it will be used as the default overrides for all test
|
|
* functions.
|
|
* The following are equivalent:
|
|
* ```ts
|
|
* test("<test_name>", [{ method: "<contract_function_name>", overrides: { from: "0x123" } }])
|
|
* test("<test_name>", [{ method: "<contract_function_name>" }], { from: "0x123" })
|
|
* ```
|
|
* In the above cases, the `from` override must be a signer.
|
|
* The `shouldFail` property can be used to indicate that the test function should fail. This should be used sparingly
|
|
* as it is not possible to match on the failure reason.
|
|
* Furthermore, the `debug` property can be used to print any thrown errors when attempting to
|
|
* send a transaction or while waiting for the transaction to be confirmed (the transaction is the smart contract call).
|
|
* `debug` will also cause any parseable event logs to be printed that start with the `log_` prefix.
|
|
* `DSTest` contracts have several options for emitting `log_` events.
|
|
*
|
|
*/
|
|
|
|
// Below are the types that help define all the different ways to call `test`
|
|
type FnNameOrObject = string | string[] | MethodObject | MethodObject[]
|
|
|
|
// Limit `from` property to be a `string` instead of `string | Promise<string>`
|
|
type Overrides = CallOverrides & { from?: string }
|
|
|
|
type MethodObject = { method: string, debug?: boolean, overrides?: Overrides, shouldFail?: boolean }
|
|
|
|
// This type is after all default values have been applied
|
|
type MethodWithDebugAndOverrides = MethodObject & { debug: boolean, overrides: Overrides, shouldFail: boolean }
|
|
|
|
// `test` is used very similarly to `it` from Mocha
|
|
export const test = (name, fnNameOrObject, overrides = {}) => it(name, buildTestFn(fnNameOrObject, overrides))
|
|
// `test.only` is used very similarly to `it.only` from Mocha, it will isolate all tests marked with `test.only`
|
|
test.only = (name, fnNameOrObject, overrides = {}) => it.only(name, buildTestFn(fnNameOrObject, overrides))
|
|
// `test.debug` is used to apply `debug: true` to all DSTest contract method calls in the test
|
|
test.debug = (name, fnNameOrObject, overrides = {}) => it.only(name, buildTestFn(fnNameOrObject, overrides, true))
|
|
// `test.skip` is used very similarly to `it.skip` from Mocha, it will skip all tests marked with `test.skip`
|
|
test.skip = (name, fnNameOrObject, overrides = {}) => it.skip(name, buildTestFn(fnNameOrObject, overrides))
|
|
|
|
// `buildTestFn` is a higher-order function. It returns a function that can be used as the test function for `it`
|
|
const buildTestFn = (fnNameOrObject: FnNameOrObject, overrides = {}, debug = false) => {
|
|
// normalize the input to an array of objects
|
|
const fnObjects: MethodWithDebugAndOverrides[] = (Array.isArray(fnNameOrObject) ? fnNameOrObject : [fnNameOrObject]).map(fnNameOrObject => {
|
|
fnNameOrObject = typeof fnNameOrObject === 'string' ? { method: fnNameOrObject } : fnNameOrObject
|
|
// assign all default values and overrides
|
|
fnNameOrObject.overrides = Object.assign({}, overrides, fnNameOrObject.overrides ?? {})
|
|
fnNameOrObject.debug = fnNameOrObject.debug ?? debug
|
|
fnNameOrObject.shouldFail = fnNameOrObject.shouldFail ?? false
|
|
|
|
return fnNameOrObject as MethodWithDebugAndOverrides
|
|
})
|
|
|
|
// only `step_` prefixed functions can be called on the `DSTest` contracts to clearly separate tests and helpers
|
|
assert(fnObjects.every(({ method }) => method.startsWith('step_')), "Solidity test functions must be prefixed with 'step_'")
|
|
|
|
// return the test function that will be used by `it`
|
|
// this function must be defined with the `function` keyword so that `this` is bound to the Mocha context
|
|
return async function () {
|
|
// `Array.prototype.reduce` is used here to ensure that the test functions are called in order.
|
|
// Each test function waits for its predecessor to complete before starting
|
|
return fnObjects.reduce((p: Promise<undefined>, fn) => p.then(async () => {
|
|
const contract = fn.overrides.from
|
|
? this.testContract.connect(await ethers.getSigner(fn.overrides.from))
|
|
: this.testContract
|
|
const tx = await contract[fn.method](fn.overrides).catch(err => {
|
|
if (fn.shouldFail) {
|
|
if (fn.debug) console.error(`smart contract call failed with error:\n${err}\n`)
|
|
|
|
return { failed: true }
|
|
}
|
|
|
|
console.error("smart contract call failed with error:", err)
|
|
throw err
|
|
})
|
|
|
|
// no more assertions necessary if the method-call should fail and did fail
|
|
if (tx.failed && fn.shouldFail) return
|
|
|
|
const txReceipt = await tx.wait().catch(err => {
|
|
if (fn.debug) console.error(`tx failed with error:\n${err}\n`)
|
|
return err.receipt
|
|
})
|
|
|
|
// `txReceipt.status` will be `0` if the transaction failed.
|
|
// `contract.callStatic.failed()` will return `true` if any of the `DSTest` assertions failed.
|
|
const failed = txReceipt.status === 0 ? true : await contract.callStatic.failed()
|
|
if (fn.debug || failed) {
|
|
console.log('')
|
|
|
|
if (!txReceipt.events) console.warn('WARNING: No parseable events found in tx-receipt\n')
|
|
|
|
// If `DSTest` assertions failed, the contract will emit logs describing the assertion failure(s).
|
|
txReceipt
|
|
.events
|
|
?.filter(event => fn.debug || event.event?.startsWith('log'))
|
|
.map(event => event.args?.forEach(arg => console.log(arg)))
|
|
|
|
console.log('')
|
|
}
|
|
|
|
if (fn.shouldFail) {
|
|
assert(failed, `${fn.method} should have failed`)
|
|
} else {
|
|
assert(!failed, `${fn.method} failed`)
|
|
}
|
|
}), Promise.resolve())
|
|
}
|
|
}
|
|
|
|
export const Roles = {
|
|
None: 0,
|
|
Enabled: 1,
|
|
Admin: 2,
|
|
Manager: 3,
|
|
}
|