From b15ca98687ffb192ea1062ffebeb09ed59842e66 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Tue, 28 Feb 2023 12:30:00 +0400 Subject: [PATCH 1/5] add generic errors for integrity operand overflow and underflow --- contracts/interpreter/deploy/LibIntegrityCheck.sol | 10 ++++++++++ contracts/interpreter/ops/tier/OpSelectLte.sol | 10 +++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/contracts/interpreter/deploy/LibIntegrityCheck.sol b/contracts/interpreter/deploy/LibIntegrityCheck.sol index 8cace1c22..e865d2e28 100644 --- a/contracts/interpreter/deploy/LibIntegrityCheck.sol +++ b/contracts/interpreter/deploy/LibIntegrityCheck.sol @@ -16,6 +16,16 @@ StackPointer constant INITIAL_STACK_BOTTOM = StackPointer.wrap( type(uint256).max / 2 ); +/// Thrown by an integrity check on an op if the operand exceeds the max value +/// that it can handle. MAY be for a subset of all the operand bits if the range +/// is over a destructured value from the whole operand. +error OperandOverflow(uint256 maximum, uint256 actual); + +/// Thrown by an integrity check on an op if the operand subseeds the min value +/// that it can handle. MAY be for a subset of all the operand bits if the range +/// is over a destructured value from the whole operand. +error OperandUnderflow(uint256 minimum, uint256 actual); + /// It is a misconfiguration to set the initial stack bottom to zero or some /// small value as this trivially exposes the integrity check to potential /// underflow issues that are gas intensive to repeatedly guard against on every diff --git a/contracts/interpreter/ops/tier/OpSelectLte.sol b/contracts/interpreter/ops/tier/OpSelectLte.sol index affe09c5d..60769695f 100644 --- a/contracts/interpreter/ops/tier/OpSelectLte.sol +++ b/contracts/interpreter/ops/tier/OpSelectLte.sol @@ -7,9 +7,6 @@ import "../../run/LibInterpreterState.sol"; import "../../deploy/LibIntegrityCheck.sol"; import "../../../math/Binary.sol"; -/// Zero inputs to select lte is NOT supported. -error ZeroInputs(); - /// @title OpSelectLte /// @notice Exposes `TierwiseCombine.selectLte` as an opcode. library OpSelectLte { @@ -23,14 +20,13 @@ library OpSelectLte { StackPointer stackTop_ ) internal pure returns (StackPointer) { unchecked { - uint256 inputs_ = Operand.unwrap(operand_) & MASK_8BIT; - if (inputs_ == 0) { - revert ZeroInputs(); + if (Operand.unwrap(operand_) == 0) { + revert OperandUnderflow(1, 0); } return integrityCheckState_.push( - integrityCheckState_.pop(stackTop_, inputs_) + integrityCheckState_.pop(stackTop_, Operand.unwrap(operand_)) ); } } From 39fc8c6b701848726a73fbd313fbe28eb9596ecb Mon Sep 17 00:00:00 2001 From: Siddharth2207 Date: Wed, 1 Mar 2023 12:14:17 +0530 Subject: [PATCH 2/5] first pass at validateMeta --- .../RainterpreterExpressionDeployer.sol | 4 +- test/Interpreter/Ops/Crypto/validateMeta.ts | 101 ++++++++++++++++++ 2 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 test/Interpreter/Ops/Crypto/validateMeta.ts diff --git a/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol b/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol index 72ef6d048..ce1168caa 100644 --- a/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol +++ b/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol @@ -43,12 +43,12 @@ bytes constant OPCODE_FUNCTION_POINTERS = hex"0aa60ab50ac40b470b550bab0bfd0c7b0c /// @dev Hash of the known interpreter bytecode. bytes32 constant INTERPRETER_BYTECODE_HASH = bytes32( - 0xdab95293aa5d21450d6c3268640614cac2f7c55a318377e2de363a3aac8568a8 + 0x45d975718aea9972992628f99acddd6e484f5724d67e94b3fdd4193d3aaaa30f ); /// @dev Hash of the known store bytecode. bytes32 constant STORE_BYTECODE_HASH = bytes32( - 0x33612e3d92c79aeb4108030de9f132698ba8563f5219fa6c32d88b3ea02040ae + 0x529e4a275f269ea91d28c434c037bc10c8a85f2f35a83201b7883b817edc254d ); /// @dev Hash of the known op meta. diff --git a/test/Interpreter/Ops/Crypto/validateMeta.ts b/test/Interpreter/Ops/Crypto/validateMeta.ts new file mode 100644 index 000000000..0643632f8 --- /dev/null +++ b/test/Interpreter/Ops/Crypto/validateMeta.ts @@ -0,0 +1,101 @@ +import { assert } from "chai"; +import { BytesLike, concat } from "ethers/lib/utils"; +import { ethers } from "hardhat"; +import { IInterpreterV1Consumer, Rainterpreter } from "../../../../typechain"; +import { max_uint256, memoryOperand, MemoryType, op, Opcode, randomUint256, standardEvaluableConfig } from "../../../../utils"; +import { rainterpreterDeploy } from "../../../../utils/deploy/interpreter/shared/rainterpreter/deploy"; +import deploy1820 from "../../../../utils/deploy/registry1820/deploy"; +import { expressionConsumerDeploy } from "../../../../utils/deploy/test/iinterpreterV1Consumer/deploy"; +import OpHash from "../../../../contracts/interpreter/ops/crypto/OpHash.opmeta.json" + + +describe("HASH Opcode test", async function () { + let rainInterpreter: Rainterpreter; + let logic: IInterpreterV1Consumer; + + before(async () => { + // Deploy ERC1820Registry + const signers = await ethers.getSigners(); + await deploy1820(signers[0]); + rainInterpreter = await rainterpreterDeploy(); + + const consumerFactory = await ethers.getContractFactory( + "IInterpreterV1Consumer" + ); + logic = (await consumerFactory.deploy()) as IInterpreterV1Consumer; + await logic.deployed(); + }); + + const getArrayOfLength = (length) => { + let arr = [] + for(let i = 0 ; i < length ; i++){ + arr.push(randomUint256()) + } + return arr + } + + const randomIntFromInterval = (min, max) => { // min and max included + return Math.floor(Math.random() * (max - min + 1) + min) + } + + const buildSources = (constants) => { + let soruceArray = [] + for(let i = 0 ; i < constants.length ; i++){ + soruceArray.push( + op(Opcode.read_memory, memoryOperand(MemoryType.Constant, constants[i])) + ) + } + let sources = concat(soruceArray) + return sources + + } + + const opHashBuilder = () => { + let opreand = OpHash.operand[0] + let rangeInput = randomIntFromInterval(opreand.validRange[0][0],opreand.validRange[0][1]) // picking from range + let bitsToShift = randomIntFromInterval(opreand.bits[0],opreand.bits[1]) + + let inputLength = rangeInput << bitsToShift + console.log("inputLength : " , inputLength ) + let constants = getArrayOfLength(rangeInput) + let sources = buildSources(constants) + + return { + sources , + constants + } + + } + + it.only("should hash a single value", async () => { + + const {sources , constants} = opHashBuilder() + + const expression0 = await expressionConsumerDeploy( + [sources], + constants, + rainInterpreter, + 1 + ); + + await logic["eval(address,uint256,uint256[][])"]( + rainInterpreter.address, + expression0.dispatch, + [] + ); + const result = await logic.stackTop(); + const expectedValue = ethers.utils.solidityKeccak256( + ["uint256[]"], + [constants] + ); + + assert( + result.eq(expectedValue), + `Invalid output, expected ${expectedValue}, actual ${result}` + ); + + }); + + + +}); From fd3d8a0e27e1ef9f54512b3532e3a2cf3f112e32 Mon Sep 17 00:00:00 2001 From: Siddharth2207 Date: Wed, 1 Mar 2023 14:26:31 +0530 Subject: [PATCH 3/5] Added custom error --- contracts/interpreter/ops/crypto/OpHash.sol | 7 +++- .../RainterpreterExpressionDeployer.sol | 2 +- test/Interpreter/Ops/Crypto/validateMeta.ts | 36 +++++++++++++++++-- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/contracts/interpreter/ops/crypto/OpHash.sol b/contracts/interpreter/ops/crypto/OpHash.sol index ea7af1c42..c6c0cfe0a 100644 --- a/contracts/interpreter/ops/crypto/OpHash.sol +++ b/contracts/interpreter/ops/crypto/OpHash.sol @@ -22,7 +22,12 @@ library OpHash { IntegrityCheckState memory integrityCheckState_, Operand operand_, StackPointer stackTop_ - ) internal pure returns (StackPointer) { + ) internal pure returns (StackPointer) { + + if (Operand.unwrap(operand_) == 0) { + revert OperandUnderflow(1, 0); + } + return integrityCheckState_.applyFn( stackTop_, diff --git a/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol b/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol index ce1168caa..1bf800567 100644 --- a/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol +++ b/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol @@ -43,7 +43,7 @@ bytes constant OPCODE_FUNCTION_POINTERS = hex"0aa60ab50ac40b470b550bab0bfd0c7b0c /// @dev Hash of the known interpreter bytecode. bytes32 constant INTERPRETER_BYTECODE_HASH = bytes32( - 0x45d975718aea9972992628f99acddd6e484f5724d67e94b3fdd4193d3aaaa30f + 0xb96735ede8dbd63dcebfb8216fab2b785373793acd09e63bbe944a3b10832326 ); /// @dev Hash of the known store bytecode. diff --git a/test/Interpreter/Ops/Crypto/validateMeta.ts b/test/Interpreter/Ops/Crypto/validateMeta.ts index 0643632f8..fc4c532ef 100644 --- a/test/Interpreter/Ops/Crypto/validateMeta.ts +++ b/test/Interpreter/Ops/Crypto/validateMeta.ts @@ -2,7 +2,7 @@ import { assert } from "chai"; import { BytesLike, concat } from "ethers/lib/utils"; import { ethers } from "hardhat"; import { IInterpreterV1Consumer, Rainterpreter } from "../../../../typechain"; -import { max_uint256, memoryOperand, MemoryType, op, Opcode, randomUint256, standardEvaluableConfig } from "../../../../utils"; +import { assertError, max_uint256, memoryOperand, MemoryType, op, Opcode, randomUint256, standardEvaluableConfig } from "../../../../utils"; import { rainterpreterDeploy } from "../../../../utils/deploy/interpreter/shared/rainterpreter/deploy"; import deploy1820 from "../../../../utils/deploy/registry1820/deploy"; import { expressionConsumerDeploy } from "../../../../utils/deploy/test/iinterpreterV1Consumer/deploy"; @@ -67,7 +67,7 @@ describe("HASH Opcode test", async function () { } - it.only("should hash a single value", async () => { + it("should hash ", async () => { const {sources , constants} = opHashBuilder() @@ -94,7 +94,37 @@ describe("HASH Opcode test", async function () { `Invalid output, expected ${expectedValue}, actual ${result}` ); - }); + }); + + it("should fail with Underflow", async () => { + const constants = [ethers.constants.MaxUint256]; + + let op_ = 1 << 1 + console.log("op_ : " , op_ ) + + // prettier-ignore + const source = concat([ + op(Opcode.read_memory, memoryOperand(MemoryType.Constant, 0)), + op(Opcode.hash, op_), + ]); + + + await assertError( + async () => + await expressionConsumerDeploy( + [source], + constants, + rainInterpreter, + 1 + ), + "OperandUnderflow", + "Did not overflow" + ) + + + + + }); From 039831e725e1d0ba15c12b82b915d3b7873aa5bb Mon Sep 17 00:00:00 2001 From: Siddharth2207 Date: Thu, 2 Mar 2023 21:04:32 +0530 Subject: [PATCH 4/5] erc20 meta-test added --- test/Interpreter/Ops/Token/erc20.ts | 71 ++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/test/Interpreter/Ops/Token/erc20.ts b/test/Interpreter/Ops/Token/erc20.ts index 297c6bf0c..21540ddb6 100644 --- a/test/Interpreter/Ops/Token/erc20.ts +++ b/test/Interpreter/Ops/Token/erc20.ts @@ -1,21 +1,25 @@ import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { assert } from "chai"; +import { concat } from "ethers/lib/utils"; import { ethers } from "hardhat"; import type { IInterpreterV1Consumer, Rainterpreter, ReserveToken, } from "../../../../typechain"; +import { assertError, randomUint256 } from "../../../../utils"; import { basicDeploy } from "../../../../utils/deploy/basicDeploy"; import { rainterpreterDeploy } from "../../../../utils/deploy/interpreter/shared/rainterpreter/deploy"; import deploy1820 from "../../../../utils/deploy/registry1820/deploy"; import { expressionConsumerDeploy } from "../../../../utils/deploy/test/iinterpreterV1Consumer/deploy"; -import { standardEvaluableConfig } from "../../../../utils/interpreter/interpreter"; +import { memoryOperand, MemoryType, op, standardEvaluableConfig } from "../../../../utils/interpreter/interpreter"; +import { AllStandardOps } from "../../../../utils/interpreter/ops/allStandardOps"; let signers: SignerWithAddress[]; let signer1: SignerWithAddress; let tokenERC20: ReserveToken; +const Opcode = AllStandardOps; describe("RainInterpreter ERC20 ops", async function () { let rainInterpreter: Rainterpreter; @@ -41,7 +45,11 @@ describe("RainInterpreter ERC20 ops", async function () { tokenERC20 = (await basicDeploy("ReserveToken", {})) as ReserveToken; await tokenERC20.initialize(); - }); + }); + + const randomUintLen = (len:number): string => { + return ethers.utils.hexZeroPad(ethers.utils.randomBytes(len), len); + } it("should return ERC20 total supply", async () => { const { sources, constants } = await standardEvaluableConfig( @@ -66,11 +74,12 @@ describe("RainInterpreter ERC20 ops", async function () { result0.eq(totalTokenSupply), `expected ${totalTokenSupply}, got ${result0}` ); - }); + }); + + it("should return ERC20 balance", async () => { - it("should return ERC20 balance", async () => { const { sources, constants } = await standardEvaluableConfig( - `_: erc-20-balance-of(${tokenERC20.address} ${signer1.address});` + `_: erc-20-balance-of(${randomUintLen(20)} ${signer1.address});` ); const expression0 = await expressionConsumerDeploy( @@ -96,5 +105,55 @@ describe("RainInterpreter ERC20 ops", async function () { ); const result1 = await logic.stackTop(); assert(result1.eq(100), `expected 100, got ${result1}`); - }); + }); + + it.only("should validate meta for ERC20 balance" , async () => { + + for(let i = 0 ; i < 10 ; i++){ + const constants = [randomUintLen(20), randomUintLen(20)]; // can be random 32 byte value as well + const vSigner1 = op( + Opcode.read_memory, + memoryOperand(MemoryType.Constant, 0) + ); + const vTokenAddr = op( + Opcode.read_memory, + memoryOperand(MemoryType.Constant, 1) + ); + + // prettier-ignore + const sources = [ + concat([ + vTokenAddr, + vSigner1, + op(Opcode.erc_20_balance_of) + ]), + ]; + + const expression0 = await expressionConsumerDeploy( + sources, + constants, + rainInterpreter, + 1 + ); + + assertError( + async () => await logic["eval(address,uint256,uint256[][])"]( + rainInterpreter.address, + expression0.dispatch, + [] + ) , + "" , + "Did not error" + ) + + } + + + }) + + + + + + }); From 9a423417828b976db4fd496a9808f0b7c04dfc0a Mon Sep 17 00:00:00 2001 From: Siddharth2207 Date: Sat, 4 Mar 2023 11:23:02 +0530 Subject: [PATCH 5/5] validate meta test updated --- contracts/interpreter/ops/crypto/OpHash.sol | 12 +- .../interpreter/ops/tier/OpSelectLte.sol | 5 +- .../RainterpreterExpressionDeployer.sol | 2 +- test/Interpreter/Ops/Crypto/validateMeta.ts | 230 ++++++++++-------- test/Interpreter/Ops/Token/erc20.ts | 72 +----- 5 files changed, 151 insertions(+), 170 deletions(-) diff --git a/contracts/interpreter/ops/crypto/OpHash.sol b/contracts/interpreter/ops/crypto/OpHash.sol index c6c0cfe0a..21bd0cc3b 100644 --- a/contracts/interpreter/ops/crypto/OpHash.sol +++ b/contracts/interpreter/ops/crypto/OpHash.sol @@ -6,6 +6,7 @@ import "../../../array/LibUint256Array.sol"; import "../../../type/LibCast.sol"; import "../../run/LibInterpreterState.sol"; import "../../deploy/LibIntegrityCheck.sol"; +import "hardhat/console.sol"; /// @title OpHash /// @notice Opcode for hashing a list of values. @@ -22,11 +23,14 @@ library OpHash { IntegrityCheckState memory integrityCheckState_, Operand operand_, StackPointer stackTop_ - ) internal pure returns (StackPointer) { - + ) internal pure returns (StackPointer) { if (Operand.unwrap(operand_) == 0) { - revert OperandUnderflow(1, 0); - } + revert OperandUnderflow(1, 0); + } + + if (Operand.unwrap(operand_) > 255) { + revert OperandOverflow(255, Operand.unwrap(operand_)); + } return integrityCheckState_.applyFn( diff --git a/contracts/interpreter/ops/tier/OpSelectLte.sol b/contracts/interpreter/ops/tier/OpSelectLte.sol index 60769695f..06cd44d4c 100644 --- a/contracts/interpreter/ops/tier/OpSelectLte.sol +++ b/contracts/interpreter/ops/tier/OpSelectLte.sol @@ -26,7 +26,10 @@ library OpSelectLte { return integrityCheckState_.push( - integrityCheckState_.pop(stackTop_, Operand.unwrap(operand_)) + integrityCheckState_.pop( + stackTop_, + Operand.unwrap(operand_) + ) ); } } diff --git a/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol b/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol index eab2e90db..312dfc5fb 100644 --- a/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol +++ b/contracts/interpreter/shared/RainterpreterExpressionDeployer.sol @@ -43,7 +43,7 @@ bytes constant OPCODE_FUNCTION_POINTERS = hex"0b360b450b540bd70be50c3b0c8d0d0b0d /// @dev Hash of the known interpreter bytecode. bytes32 constant INTERPRETER_BYTECODE_HASH = bytes32( - 0x482a1bf899b7982e643e48819e46d9ecc129479cfbc6986db85cfa56cf396837 + 0x078bc41915d9b0546cf9af619740692cca28489e388a79d381c14e7752de9baf ); /// @dev Hash of the known store bytecode. diff --git a/test/Interpreter/Ops/Crypto/validateMeta.ts b/test/Interpreter/Ops/Crypto/validateMeta.ts index fc4c532ef..92a30224b 100644 --- a/test/Interpreter/Ops/Crypto/validateMeta.ts +++ b/test/Interpreter/Ops/Crypto/validateMeta.ts @@ -2,12 +2,21 @@ import { assert } from "chai"; import { BytesLike, concat } from "ethers/lib/utils"; import { ethers } from "hardhat"; import { IInterpreterV1Consumer, Rainterpreter } from "../../../../typechain"; -import { assertError, max_uint256, memoryOperand, MemoryType, op, Opcode, randomUint256, standardEvaluableConfig } from "../../../../utils"; +import { + assertError, + max_uint256, + memoryOperand, + MemoryType, + op, + Opcode, + randomUint256, + standardEvaluableConfig, +} from "../../../../utils"; import { rainterpreterDeploy } from "../../../../utils/deploy/interpreter/shared/rainterpreter/deploy"; import deploy1820 from "../../../../utils/deploy/registry1820/deploy"; -import { expressionConsumerDeploy } from "../../../../utils/deploy/test/iinterpreterV1Consumer/deploy"; -import OpHash from "../../../../contracts/interpreter/ops/crypto/OpHash.opmeta.json" - +import { expressionConsumerDeploy } from "../../../../utils/deploy/test/iinterpreterV1Consumer/deploy"; +import OpHash from "../../../../contracts/interpreter/ops/crypto/OpHash.opmeta.json"; +import { constructByBits, OperandArgs } from "rainlang"; describe("HASH Opcode test", async function () { let rainInterpreter: Rainterpreter; @@ -24,108 +33,119 @@ describe("HASH Opcode test", async function () { ); logic = (await consumerFactory.deploy()) as IInterpreterV1Consumer; await logic.deployed(); - }); - - const getArrayOfLength = (length) => { - let arr = [] - for(let i = 0 ; i < length ; i++){ - arr.push(randomUint256()) - } - return arr - } - - const randomIntFromInterval = (min, max) => { // min and max included - return Math.floor(Math.random() * (max - min + 1) + min) - } - - const buildSources = (constants) => { - let soruceArray = [] - for(let i = 0 ; i < constants.length ; i++){ + }); + + // get array of a particualr length + const getArrayOfLength = (length: number) => { + let arr = []; + for (let i = 0; i < length; i++) { + arr.push(randomUint256()); + } + return arr; + }; + + // get a int between min and max inclusive + const randomIntFromInterval = (min: number, max: number) => { + return Math.floor(Math.random() * (max - min + 1) + min); + }; + + // build source array from constants array + const buildSources = (constants: Array, op_: number | number[]) => { + let soruceArray = []; + for (let i = 0; i < constants.length; i++) { soruceArray.push( - op(Opcode.read_memory, memoryOperand(MemoryType.Constant, constants[i])) - ) - } - let sources = concat(soruceArray) - return sources - - } - - const opHashBuilder = () => { - let opreand = OpHash.operand[0] - let rangeInput = randomIntFromInterval(opreand.validRange[0][0],opreand.validRange[0][1]) // picking from range - let bitsToShift = randomIntFromInterval(opreand.bits[0],opreand.bits[1]) - - let inputLength = rangeInput << bitsToShift - console.log("inputLength : " , inputLength ) - let constants = getArrayOfLength(rangeInput) - let sources = buildSources(constants) - - return { - sources , - constants + op(Opcode.read_memory, memoryOperand(MemoryType.Constant, i)) + ); + } + soruceArray.push(op(Opcode.hash, op_)); + let sources = concat(soruceArray); + return sources; + }; + + it("should build operand from array of fuzzed? operand values ", async () => { + for (let i = 0; i < 30; i++) { + // get random value for range + let range = randomIntFromInterval(1, 300); + + let operandArgs: OperandArgs = [ + { + name: "", + bits: [0, 7], + validRange: [[1, range]], + }, + ]; + + // array of values that will be build as a single operand + let values = [range]; + const constants = getArrayOfLength(range); + + // Constructing arguments for the constructByBits function + // ref resolveOp method of rain parser + let constructArgs = operandArgs.map((e, i) => { + return { + value: values[i], + bits: e.bits, + computation: e.computation, + validRange: e.validRange, + }; + }); + + // getting the operand + let op_ = constructByBits(constructArgs); + let source = buildSources(constants, op_); + + // Case if operand is zero + if (op_[0] === 0) { + await assertError( + async () => + await expressionConsumerDeploy( + [source], + constants, + rainInterpreter, + 1 + ), + "OperandUnderflow", + "Underflow" + ); + } else if (op_[0] > 255) { + // Case if operand is greater than enforced length + + await assertError( + async () => + await expressionConsumerDeploy( + [source], + constants, + rainInterpreter, + 1 + ), + "OperandOverflow", + "Overflow" + ); + } else { + const expression0 = await expressionConsumerDeploy( + [source], + constants, + rainInterpreter, + 1 + ); + + await logic["eval(address,uint256,uint256[][])"]( + rainInterpreter.address, + expression0.dispatch, + [] + ); + const result = await logic.stackTop(); + + const expectedValue = ethers.utils.solidityKeccak256( + ["uint256[]"], + [constants] + ); + + assert( + result.eq(expectedValue), + `Invalid output, expected ${expectedValue}, actual ${result}` + ); + } } - - } - - it("should hash ", async () => { - - const {sources , constants} = opHashBuilder() - - const expression0 = await expressionConsumerDeploy( - [sources], - constants, - rainInterpreter, - 1 - ); - - await logic["eval(address,uint256,uint256[][])"]( - rainInterpreter.address, - expression0.dispatch, - [] - ); - const result = await logic.stackTop(); - const expectedValue = ethers.utils.solidityKeccak256( - ["uint256[]"], - [constants] - ); - - assert( - result.eq(expectedValue), - `Invalid output, expected ${expectedValue}, actual ${result}` - ); - - }); - - it("should fail with Underflow", async () => { - const constants = [ethers.constants.MaxUint256]; - - let op_ = 1 << 1 - console.log("op_ : " , op_ ) - - // prettier-ignore - const source = concat([ - op(Opcode.read_memory, memoryOperand(MemoryType.Constant, 0)), - op(Opcode.hash, op_), - ]); - - - await assertError( - async () => - await expressionConsumerDeploy( - [source], - constants, - rainInterpreter, - 1 - ), - "OperandUnderflow", - "Did not overflow" - ) - - - - }); - - - }); diff --git a/test/Interpreter/Ops/Token/erc20.ts b/test/Interpreter/Ops/Token/erc20.ts index 21540ddb6..eac570653 100644 --- a/test/Interpreter/Ops/Token/erc20.ts +++ b/test/Interpreter/Ops/Token/erc20.ts @@ -12,7 +12,12 @@ import { basicDeploy } from "../../../../utils/deploy/basicDeploy"; import { rainterpreterDeploy } from "../../../../utils/deploy/interpreter/shared/rainterpreter/deploy"; import deploy1820 from "../../../../utils/deploy/registry1820/deploy"; import { expressionConsumerDeploy } from "../../../../utils/deploy/test/iinterpreterV1Consumer/deploy"; -import { memoryOperand, MemoryType, op, standardEvaluableConfig } from "../../../../utils/interpreter/interpreter"; +import { + memoryOperand, + MemoryType, + op, + standardEvaluableConfig, +} from "../../../../utils/interpreter/interpreter"; import { AllStandardOps } from "../../../../utils/interpreter/ops/allStandardOps"; let signers: SignerWithAddress[]; @@ -45,11 +50,11 @@ describe("RainInterpreter ERC20 ops", async function () { tokenERC20 = (await basicDeploy("ReserveToken", {})) as ReserveToken; await tokenERC20.initialize(); - }); + }); - const randomUintLen = (len:number): string => { + const randomUintLen = (len: number): string => { return ethers.utils.hexZeroPad(ethers.utils.randomBytes(len), len); - } + }; it("should return ERC20 total supply", async () => { const { sources, constants } = await standardEvaluableConfig( @@ -74,12 +79,11 @@ describe("RainInterpreter ERC20 ops", async function () { result0.eq(totalTokenSupply), `expected ${totalTokenSupply}, got ${result0}` ); - }); - - it("should return ERC20 balance", async () => { + }); + it("should return ERC20 balance", async () => { const { sources, constants } = await standardEvaluableConfig( - `_: erc-20-balance-of(${randomUintLen(20)} ${signer1.address});` + `_: erc-20-balance-of(${tokenERC20.address} ${signer1.address});` ); const expression0 = await expressionConsumerDeploy( @@ -105,55 +109,5 @@ describe("RainInterpreter ERC20 ops", async function () { ); const result1 = await logic.stackTop(); assert(result1.eq(100), `expected 100, got ${result1}`); - }); - - it.only("should validate meta for ERC20 balance" , async () => { - - for(let i = 0 ; i < 10 ; i++){ - const constants = [randomUintLen(20), randomUintLen(20)]; // can be random 32 byte value as well - const vSigner1 = op( - Opcode.read_memory, - memoryOperand(MemoryType.Constant, 0) - ); - const vTokenAddr = op( - Opcode.read_memory, - memoryOperand(MemoryType.Constant, 1) - ); - - // prettier-ignore - const sources = [ - concat([ - vTokenAddr, - vSigner1, - op(Opcode.erc_20_balance_of) - ]), - ]; - - const expression0 = await expressionConsumerDeploy( - sources, - constants, - rainInterpreter, - 1 - ); - - assertError( - async () => await logic["eval(address,uint256,uint256[][])"]( - rainInterpreter.address, - expression0.dispatch, - [] - ) , - "" , - "Did not error" - ) - - } - - - }) - - - - - - + }); });