From 2c9adbcc662521bffb126877626d531be1792ab3 Mon Sep 17 00:00:00 2001 From: funderbrker Date: Fri, 9 Feb 2024 19:47:24 -0500 Subject: [PATCH 01/13] init commit. placeholders. --- .../src/lib/tractor/OperatorPasteInstrs.ts | 16 ++++++++++ projects/sdk/src/lib/tractor/drafter.ts | 30 +++++++++++++++++++ projects/sdk/src/lib/tractor/tractor.test.ts | 0 projects/sdk/src/lib/tractor/tractor.ts | 24 +++++++++++++++ projects/sdk/src/lib/tractor/types.ts | 26 ++++++++++++++++ 5 files changed, 96 insertions(+) create mode 100644 projects/sdk/src/lib/tractor/OperatorPasteInstrs.ts create mode 100644 projects/sdk/src/lib/tractor/drafter.ts create mode 100644 projects/sdk/src/lib/tractor/tractor.test.ts create mode 100644 projects/sdk/src/lib/tractor/tractor.ts create mode 100644 projects/sdk/src/lib/tractor/types.ts diff --git a/projects/sdk/src/lib/tractor/OperatorPasteInstrs.ts b/projects/sdk/src/lib/tractor/OperatorPasteInstrs.ts new file mode 100644 index 0000000000..3d3b0e974a --- /dev/null +++ b/projects/sdk/src/lib/tractor/OperatorPasteInstrs.ts @@ -0,0 +1,16 @@ +import { BeanstalkSDK } from "../BeanstalkSDK"; +import { uint80, Bytes32 } from "./types"; + +export class OperatorPasteInstrs { + static sdk: BeanstalkSDK; + + constructor(sdk: BeanstalkSDK) { + OperatorPasteInstrs.sdk = sdk; + } + + encode(copyByteIndex: uint80, pasteCallIndex: uint80, pasteByteIndex: uint80): Bytes32 { return ''; } + + decode(operatorPasteInstr: Bytes32): [uint80, uint80, uint80] { return ['', '', ''] } + + +} diff --git a/projects/sdk/src/lib/tractor/drafter.ts b/projects/sdk/src/lib/tractor/drafter.ts new file mode 100644 index 0000000000..6b3ee9371e --- /dev/null +++ b/projects/sdk/src/lib/tractor/drafter.ts @@ -0,0 +1,30 @@ +import { BeanstalkSDK } from "../BeanstalkSDK"; + +import {Clipboard} from '../depot/clipboard' +import {OperatorPasteInstrs} from './OperatorPasteInstrs' + +export class Drafter { + static sdk: BeanstalkSDK; + + clipboard : Clipboard; + operatorPasteInstrs : OperatorPasteInstrs; + + constructor(sdk: BeanstalkSDK) { + Drafter.sdk = sdk; + } + + // operatorPasteInstrs.encode() + // encodeOperatorPasteInstr(copyByteIndex : uint80, pasteCallIndex: uint80, pasteByteIndex: uint80): bytes32 {} + // operatorPasteInstrs.decode() + // decodeOperatorPasteInstr(operatorPasteInstr : bytes32): (uint80, uint80, uint80) {} + + // clipboard.pack() + // encodeLibReturnPasteParam(returnDataItemIndex : uint80, copyByteIndex: uint80, pasteByteIndex: uint80): (bytes32) {} + // clipboard.unpack() + // decodeLibReturnPasteParam(returnPasteParam : bytes32): (uint80, uint80, uint80) {} + // clipboard.encode() + // encodeClipboard(etherValue : uint256, returnPasteParams: bytes32[]): (Clipboard) {} + // clipboard.decode() + // decodeClipboard(clipboard : Clipboard): (bytes1, uint256, bytes32[]) {} + + } diff --git a/projects/sdk/src/lib/tractor/tractor.test.ts b/projects/sdk/src/lib/tractor/tractor.test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/projects/sdk/src/lib/tractor/tractor.ts b/projects/sdk/src/lib/tractor/tractor.ts new file mode 100644 index 0000000000..2b752f7c9a --- /dev/null +++ b/projects/sdk/src/lib/tractor/tractor.ts @@ -0,0 +1,24 @@ +import { BeanstalkSDK } from "../BeanstalkSDK"; +import { ethers, ContractTransaction } from "ethers"; +import { Requisition, Bytes } from "./types"; + +export class Tractor { + static sdk: BeanstalkSDK; + // publisher: Publisher; + // sequenceBuilder: BlueprintBuilder; + // operator: Operator; + // sequenceBuilder: OperatorDataBuilder; + + + constructor(sdk: BeanstalkSDK) { + Tractor.sdk = sdk; + // this.sequenceBuilder = new SequenceBuilder(sdk); + // this.operator = new Operator(sdk); + // this.publisher = new Publisher(sdk); + } + + async tractor(requisition: Requisition, operatorData: Bytes): Promise { + return Tractor.sdk.contracts.beanstalk.tractor(requisition, operatorData); + } + +} diff --git a/projects/sdk/src/lib/tractor/types.ts b/projects/sdk/src/lib/tractor/types.ts new file mode 100644 index 0000000000..bac46a5833 --- /dev/null +++ b/projects/sdk/src/lib/tractor/types.ts @@ -0,0 +1,26 @@ +import { ethers } from "ethers"; + +export type Bytes = string; +export type Bytes32 = string; +export type uint80 = string; + +export type Blueprint = { + publisher: string; + data: Bytes; + operatorPasteInstrs: Bytes32[]; + maxNonce: number; + startTime: number; + endTime: number; +} + + +export type Requisition = { + blueprint: Blueprint; + blueprintHash: Bytes32; + signature: Bytes; +} + + +function toBytes32(data: number) { + return ethers.utils.hexlify(ethers.utils.zeroPad(data.toString(), 32)); +} From 7427af75b2fc43f4aa4f37d8c57b3782c755eaf1 Mon Sep 17 00:00:00 2001 From: Drew Date: Fri, 1 Mar 2024 16:47:01 -0500 Subject: [PATCH 02/13] tractor README --- projects/sdk/src/lib/tractor/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 projects/sdk/src/lib/tractor/README.md diff --git a/projects/sdk/src/lib/tractor/README.md b/projects/sdk/src/lib/tractor/README.md new file mode 100644 index 0000000000..d935d1c976 --- /dev/null +++ b/projects/sdk/src/lib/tractor/README.md @@ -0,0 +1,22 @@ +# Tractor SDK + +Helpers for both publishers and operators using Tractor functionality. + +## Terms + +- **Tractor** - Tractor is a system that enables operators to perform arbitrary sequences of actions on behalf of a publisher. +- **Publisher** - The address that signs a Blueprint requesting actions to be performed on its behalf. Effectively msg.sender during Tractor operation. +- **Operator** - The address that executes the transaction performing the sequence of actions encoded in a Blueprint. +- **Blueprint** - A set of instructions containing metadata and a sequence of actions for the operator to perform on behalf of the publisher. +- **Requisition** - Contains a Blueprint, the blueprint hash, and the ERC-721/EIP-1271 signature of the publisher. +- **OperatorPasteInstrs** - A sequence of copy + paste runtime actions that will be performed on the calldata supplied by the operator. Note that the composition of these instructions is **not** the same as the composition of Clipboard PasteParams. +- **MaxNonce** - The maximum number of times the blueprint can be operated. + +- **Pipeline** - Independent system for performing arbitrary sequence of actions in a single transactions. See https://evmpipeline.org/pipeline.pdf. +- **Clipboard** - A component of _Pipeline_ for using return data as calldata in subsequent actions in a sequence of actions performed in the same transaction. + +## Use flow + +1. Publisher signs a Requisition containing a blueprint with a sequence of requested actions encoded in the data. Signing a transaction requires no gas, unless the Publisher wants to publish the Blueprint through on-chain events. +2. Potential Operator(s) acquire the Blueprint. Either through event monitoring, P2P sharing, or a database. +3. Operator executes the Blueprint on-chain in a single transaction, possibly including their own encoded calldata. From d187545a59459c9c587b55286e0908ab81e3cd65 Mon Sep 17 00:00:00 2001 From: Drew Date: Fri, 1 Mar 2024 16:47:27 -0500 Subject: [PATCH 03/13] drafter, used for encoding+decoding blueprint components. Draft templates --- projects/sdk/src/lib/tractor/drafter.ts | 123 ++++++++++++++++++++---- 1 file changed, 106 insertions(+), 17 deletions(-) diff --git a/projects/sdk/src/lib/tractor/drafter.ts b/projects/sdk/src/lib/tractor/drafter.ts index 6b3ee9371e..34351f17dd 100644 --- a/projects/sdk/src/lib/tractor/drafter.ts +++ b/projects/sdk/src/lib/tractor/drafter.ts @@ -1,30 +1,119 @@ +import { ethers } from "ethers"; + import { BeanstalkSDK } from "../BeanstalkSDK"; +import { Clipboard } from "../depot/clipboard"; +import { Blueprint, Requisition, Draft, AdvancedFarmCall, OperatorPasteInstr } from "./types"; -import {Clipboard} from '../depot/clipboard' -import {OperatorPasteInstrs} from './OperatorPasteInstrs' +const SELECTOR_SIZE = 4; +const SLOT_SIZE = 32; +const ARGS_START_INDEX = SELECTOR_SIZE + SLOT_SIZE; +const ADDR_SLOT_OFFSET = 12; +const PUBLISHER_COPY_INDEX = 2 ** 80 - 1; +const OPERATOR_COPY_INDEX = 2 ** 80 - 2; export class Drafter { - static sdk: BeanstalkSDK; + static sdk: BeanstalkSDK; - clipboard : Clipboard; - operatorPasteInstrs : OperatorPasteInstrs; - - constructor(sdk: BeanstalkSDK) { - Drafter.sdk = sdk; - } + constructor(sdk: BeanstalkSDK) { + Drafter.sdk = sdk; + } + + static embedDraft(blueprint: Blueprint, draft: Draft) { + blueprint.data = Drafter.encodeBlueprintData(draft.advFarmCalls); + blueprint.operatorPasteInstrs = Drafter.encodeOperatorPasteInstrs(draft.operatorPasteInstrs); + } + + static concatDrafts(firstDraft: Draft, secondDraft: Draft): Draft { + let draft = {}; + draft.advFarmCalls = firstDraft.advFarmCalls.concat(secondDraft.advFarmCalls); + draft.operatorPasteInstrs = firstDraft.operatorPasteInstrs.concat( + secondDraft.operatorPasteInstrs + ); + return draft; + } + + // encodeAdvancedFarmCalls + static encodeBlueprintData(calls: AdvancedFarmCall[]): ethers.Bytes { + // sdk.contracts.farmFacet.interface.encodeFunctionData("advancedFarm", [ + return Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("advancedFarm", [calls]); + } - // operatorPasteInstrs.encode() - // encodeOperatorPasteInstr(copyByteIndex : uint80, pasteCallIndex: uint80, pasteByteIndex: uint80): bytes32 {} - // operatorPasteInstrs.decode() - // decodeOperatorPasteInstr(operatorPasteInstr : bytes32): (uint80, uint80, uint80) {} + // static decodeBlueprintData + + static encodeOperatorPasteInstrs(instrs: OperatorPasteInstr[]): ethers.Bytes { + return ethers.utils.concat(instrs.map((instr) => Drafter.encodeOperatorPasteInstr(instr))); + } + + // Returns Bytes32 + static encodeOperatorPasteInstr(instr: OperatorPasteInstr): ethers.Bytes { + return ethers.utils.concat([ + ethers.utils.zeroPad(ethers.utils.hexValue(instr.copyByteIndex), 10), + ethers.utils.zeroPad(ethers.utils.hexValue(instr.copyByteIndex), 10), + ethers.utils.zeroPad(ethers.utils.hexValue(instr.copyByteIndex), 10), + ethers.utils.zeroPad("", 2) // padding + ]); + } + + static decodeOperatorPasteInstr(instr: ethers.Bytes): OperatorPasteInstr { + // const instrBytes: ethers.Bytes = ethers.utils.arrayify(instr); + if (instr.length != 32) { + throw TypeError("OperatorPasteInstr must be 32 bytes"); + } + return { + copyByteIndex: ethers.BigNumber.from(ethers.utils.hexDataSlice(instr, 0, 9)).toNumber(), + pasteCallIndex: ethers.BigNumber.from(ethers.utils.hexDataSlice(instr, 10, 19)).toNumber(), + pasteByteIndex: ethers.BigNumber.from(ethers.utils.hexDataSlice(instr, 20, 29)).toNumber() + }; - // clipboard.pack() // encodeLibReturnPasteParam(returnDataItemIndex : uint80, copyByteIndex: uint80, pasteByteIndex: uint80): (bytes32) {} - // clipboard.unpack() // decodeLibReturnPasteParam(returnPasteParam : bytes32): (uint80, uint80, uint80) {} - // clipboard.encode() // encodeClipboard(etherValue : uint256, returnPasteParams: bytes32[]): (Clipboard) {} - // clipboard.decode() // decodeClipboard(clipboard : Clipboard): (bytes1, uint256, bytes32[]) {} + } + + static balanceOfStalkDraft(callIndex: number): Draft { + return { + advFarmCalls: [ + { + callData: Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("balanceOfStalk", [ + ethers.constants.AddressZero + ]), + clipboard: ethers.utils.arrayify("0x000000") + } + ], + operatorPasteInstrs: [ + { + copyByteIndex: PUBLISHER_COPY_INDEX, + pasteCallIndex: callIndex, + pasteByteIndex: ARGS_START_INDEX + } + ] + }; + } + static mowDraft(callIndex: number): Draft { + return { + advFarmCalls: [ + { + callData: Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("mow", [ + ethers.constants.AddressZero, + ethers.constants.AddressZero + ]), + clipboard: ethers.utils.arrayify("0x000000") + } + ], + operatorPasteInstrs: [ + { + copyByteIndex: PUBLISHER_COPY_INDEX, + pasteCallIndex: callIndex, + pasteByteIndex: ARGS_START_INDEX + }, + { + copyByteIndex: PUBLISHER_COPY_INDEX, + pasteCallIndex: callIndex, + pasteByteIndex: ARGS_START_INDEX + SLOT_SIZE + } + ] + }; } +} From cc0580cb6f3144c152616c82395fcb06978df86a Mon Sep 17 00:00:00 2001 From: Drew Date: Fri, 1 Mar 2024 16:47:47 -0500 Subject: [PATCH 04/13] draft Mow w/ reward template, incomplete --- projects/sdk/src/lib/tractor/examples.ts | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 projects/sdk/src/lib/tractor/examples.ts diff --git a/projects/sdk/src/lib/tractor/examples.ts b/projects/sdk/src/lib/tractor/examples.ts new file mode 100644 index 0000000000..d61e2a1a3d --- /dev/null +++ b/projects/sdk/src/lib/tractor/examples.ts @@ -0,0 +1,33 @@ +// This test uses the Tractor SDK and core Tractor code. It represents how an end user would interact with Tractor. + +import { ethers } from "ethers"; +import { + AdvancedFarmCall, + Blueprint, + Draft, + OperatorPasteInstr, + encodeBlueprintData, + encodeOperatorPasteInstrs +} from "./types"; +import { Drafter } from "./drafter"; + +// Create a Blueprint to Mow the publishers stalk. +// This function represents only one approach to implement a Mow Blueprint and is inherently biased. +function createBlueprint_mow(publisher: string) { + const blueprint: Blueprint = { + publisher: publisher, + maxNonce: ethers.constants.MaxUint256, + startTime: ethers.BigNumber.from(Math.floor(Date.now() / 1000)), + endTime: ethers.constants.MaxUint256 + }; + + let draft: Draft; + + draft = Drafter.balanceOfStalkDraft(0); + draft = Drafter.concatDrafts(draft, Drafter.mowDraft(1)); + draft = Drafter.concatDrafts(draft, Drafter.balanceOfStalkDraft(2)); + draft = // need to use clipboard + + Drafter.embedDraft(blueprint, encodeBlueprintData(blueprint, draft)); + return blueprint; +} From af5138898d24a11e77f6db35d528ae42c756ce45 Mon Sep 17 00:00:00 2001 From: Drew Date: Fri, 1 Mar 2024 16:48:10 -0500 Subject: [PATCH 05/13] Tractor types --- projects/sdk/src/lib/tractor/types.ts | 44 ++++++++++++++++----------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/projects/sdk/src/lib/tractor/types.ts b/projects/sdk/src/lib/tractor/types.ts index bac46a5833..25f3931c2b 100644 --- a/projects/sdk/src/lib/tractor/types.ts +++ b/projects/sdk/src/lib/tractor/types.ts @@ -1,26 +1,34 @@ import { ethers } from "ethers"; -export type Bytes = string; -export type Bytes32 = string; -export type uint80 = string; +export type uint80 = number; export type Blueprint = { - publisher: string; - data: Bytes; - operatorPasteInstrs: Bytes32[]; - maxNonce: number; - startTime: number; - endTime: number; -} - + publisher: string; + data: ethers.Bytes; + operatorPasteInstrs?: ethers.Bytes; + maxNonce: ethers.BigNumber; + startTime: ethers.BigNumber; + endTime: ethers.BigNumber; +}; export type Requisition = { - blueprint: Blueprint; - blueprintHash: Bytes32; - signature: Bytes; -} + blueprint: Blueprint; + blueprintHash: ethers.Bytes; + signature: ethers.Bytes; +}; + +export type Draft = { + advFarmCalls: AdvancedFarmCall[]; + operatorPasteInstrs: OperatorPasteInstr[]; +}; +export type AdvancedFarmCall = { + callData: ethers.Bytes; + clipboard: ethers.Bytes; +}; -function toBytes32(data: number) { - return ethers.utils.hexlify(ethers.utils.zeroPad(data.toString(), 32)); -} +export type OperatorPasteInstr = { + copyByteIndex: uint80; + pasteCallIndex: uint80; + pasteByteIndex: uint80; +}; From e9a80e871a547d7b66aaf9b5124137112ccfb5c3 Mon Sep 17 00:00:00 2001 From: Drew Date: Mon, 4 Mar 2024 10:35:24 -0500 Subject: [PATCH 06/13] junction contract/abi (undeployed) --- .../src/constants/abi/Ecosystem/Junction.json | 341 ++++++++++++++++++ projects/sdk/src/lib/contracts.ts | 25 +- 2 files changed, 362 insertions(+), 4 deletions(-) create mode 100644 projects/sdk/src/constants/abi/Ecosystem/Junction.json diff --git a/projects/sdk/src/constants/abi/Ecosystem/Junction.json b/projects/sdk/src/constants/abi/Ecosystem/Junction.json new file mode 100644 index 0000000000..e96a11ae35 --- /dev/null +++ b/projects/sdk/src/constants/abi/Ecosystem/Junction.json @@ -0,0 +1,341 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Junction", + "sourceName": "contracts/ecosystem/junction/Junction.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "add", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "selector", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "options", + "type": "bytes32[]" + } + ], + "name": "bytes32Switch", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "condition", + "type": "bool" + } + ], + "name": "check", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "div", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "eq", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "gt", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "gte", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "lt", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "lte", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "mod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "mul", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "c", + "type": "uint256" + } + ], + "name": "mulDiv", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "neq", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "a", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "b", + "type": "uint256" + } + ], + "name": "sub", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50610681806100206000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063a391c15b1161008c578063b67d77c511610066578063b67d77c5146102cb578063c8a4ac9c146102ee578063ea6515c414610311578063f43f523a14610334576100ea565b8063a391c15b1461025c578063aa9a09121461027f578063b4773329146102a8576100ea565b806332148d73116100c857806332148d731461016a57806343df04251461018d578063771602f7146102165780637c6ed9ef14610239576100ea565b8063118fc88c146100ef57806321e5749b14610126578063241c591214610149575b600080fd5b6101126004803603604081101561010557600080fd5b5080359060200135610357565b604080519115158252519081900360200190f35b6101126004803603604081101561013c57600080fd5b5080359060200135610361565b6101686004803603602081101561015f57600080fd5b50351515610365565b005b6101126004803603604081101561018057600080fd5b50803590602001356103ba565b610204600480360360408110156101a357600080fd5b813591908101906040810160208201356401000000008111156101c557600080fd5b8201836020820111156101d757600080fd5b803590602001918460208302840111640100000000831117156101f957600080fd5b5090925090506103be565b60408051918252519081900360200190f35b6102046004803603604081101561022c57600080fd5b50803590602001356103dc565b6101126004803603604081101561024f57600080fd5b50803590602001356103ef565b6102046004803603604081101561027257600080fd5b50803590602001356103f4565b6102046004803603606081101561029557600080fd5b5080359060208101359060400135610400565b610112600480360360408110156102be57600080fd5b508035906020013561041e565b610204600480360360408110156102e157600080fd5b5080359060200135610423565b6102046004803603604081101561030457600080fd5b508035906020013561042f565b6101126004803603604081101561032757600080fd5b508035906020013561043b565b6102046004803603604081101561034a57600080fd5b5080359060200135610440565b8082105b92915050565b1090565b806103b7576040805162461bcd60e51b815260206004820152601660248201527f4a756e6374696f6e3a20636865636b206661696c656400000000000000000000604482015290519081900360640190fd5b50565b1490565b60008282858181106103cc57fe5b9050602002013590509392505050565b60006103e8838361044c565b9392505050565b141590565b60006103e883836104a6565b600061041682610410868661050d565b906104a6565b949350505050565b111590565b60006103e88383610566565b60006103e8838361050d565b101590565b60006103e883836105c3565b6000828201838110156103e8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008082116104fc576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161050557fe5b049392505050565b60008261051c5750600061035b565b8282028284828161052957fe5b04146103e85760405162461bcd60e51b815260040180806020018281038252602181526020018061062b6021913960400191505060405180910390fd5b6000828211156105bd576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000808211610619576040805162461bcd60e51b815260206004820152601860248201527f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000604482015290519081900360640190fd5b81838161062257fe5b06939250505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212201074a71d2d918252f317eb2bdd5ba7239a046902016a306f30f5df7b58c1069e64736f6c63430007060033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063a391c15b1161008c578063b67d77c511610066578063b67d77c5146102cb578063c8a4ac9c146102ee578063ea6515c414610311578063f43f523a14610334576100ea565b8063a391c15b1461025c578063aa9a09121461027f578063b4773329146102a8576100ea565b806332148d73116100c857806332148d731461016a57806343df04251461018d578063771602f7146102165780637c6ed9ef14610239576100ea565b8063118fc88c146100ef57806321e5749b14610126578063241c591214610149575b600080fd5b6101126004803603604081101561010557600080fd5b5080359060200135610357565b604080519115158252519081900360200190f35b6101126004803603604081101561013c57600080fd5b5080359060200135610361565b6101686004803603602081101561015f57600080fd5b50351515610365565b005b6101126004803603604081101561018057600080fd5b50803590602001356103ba565b610204600480360360408110156101a357600080fd5b813591908101906040810160208201356401000000008111156101c557600080fd5b8201836020820111156101d757600080fd5b803590602001918460208302840111640100000000831117156101f957600080fd5b5090925090506103be565b60408051918252519081900360200190f35b6102046004803603604081101561022c57600080fd5b50803590602001356103dc565b6101126004803603604081101561024f57600080fd5b50803590602001356103ef565b6102046004803603604081101561027257600080fd5b50803590602001356103f4565b6102046004803603606081101561029557600080fd5b5080359060208101359060400135610400565b610112600480360360408110156102be57600080fd5b508035906020013561041e565b610204600480360360408110156102e157600080fd5b5080359060200135610423565b6102046004803603604081101561030457600080fd5b508035906020013561042f565b6101126004803603604081101561032757600080fd5b508035906020013561043b565b6102046004803603604081101561034a57600080fd5b5080359060200135610440565b8082105b92915050565b1090565b806103b7576040805162461bcd60e51b815260206004820152601660248201527f4a756e6374696f6e3a20636865636b206661696c656400000000000000000000604482015290519081900360640190fd5b50565b1490565b60008282858181106103cc57fe5b9050602002013590509392505050565b60006103e8838361044c565b9392505050565b141590565b60006103e883836104a6565b600061041682610410868661050d565b906104a6565b949350505050565b111590565b60006103e88383610566565b60006103e8838361050d565b101590565b60006103e883836105c3565b6000828201838110156103e8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008082116104fc576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b81838161050557fe5b049392505050565b60008261051c5750600061035b565b8282028284828161052957fe5b04146103e85760405162461bcd60e51b815260040180806020018281038252602181526020018061062b6021913960400191505060405180910390fd5b6000828211156105bd576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000808211610619576040805162461bcd60e51b815260206004820152601860248201527f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000604482015290519081900360640190fd5b81838161062257fe5b06939250505056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a26469706673582212201074a71d2d918252f317eb2bdd5ba7239a046902016a306f30f5df7b58c1069e64736f6c63430007060033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/projects/sdk/src/lib/contracts.ts b/projects/sdk/src/lib/contracts.ts index b27d281786..302e001a67 100644 --- a/projects/sdk/src/lib/contracts.ts +++ b/projects/sdk/src/lib/contracts.ts @@ -30,6 +30,8 @@ import { Math__factory, UsdOracle, UsdOracle__factory, + Junction, + Junction__factory } from "src/constants/generated"; import { BaseContract } from "ethers"; @@ -61,6 +63,7 @@ export class Contracts { public readonly root: Root; public readonly math: Math; public readonly usdOracle: UsdOracle; + public readonly junction: Junction; public readonly curve: CurveContracts; @@ -79,6 +82,7 @@ export class Contracts { const mathAddress = sdk.addresses.MATH.get(sdk.chainId); const rootAddress = sdk.addresses.ROOT.get(sdk.chainId); const usdOracleAddress = sdk.addresses.USD_ORACLE.get(sdk.chainId); + const junctionAddress = sdk.addresses.JUNCTION.get(sdk.chainId); const beancrv3Address = sdk.addresses.BEAN_CRV3.get(sdk.chainId); const pool3Address = sdk.addresses.POOL3.get(sdk.chainId); @@ -90,21 +94,34 @@ export class Contracts { // Instances this.beanstalk = Beanstalk__factory.connect(beanstalkAddress, sdk.providerOrSigner); - this.beanstalkPrice = BeanstalkPrice__factory.connect(beanstalkPriceAddress, sdk.providerOrSigner); - this.fertilizer = BeanstalkFertilizer__factory.connect(beanstalkFertilizerAddress, sdk.providerOrSigner); + this.beanstalkPrice = BeanstalkPrice__factory.connect( + beanstalkPriceAddress, + sdk.providerOrSigner + ); + this.fertilizer = BeanstalkFertilizer__factory.connect( + beanstalkFertilizerAddress, + sdk.providerOrSigner + ); this.pipeline = Pipeline__factory.connect(pipelineAddress, sdk.providerOrSigner); this.depot = Depot__factory.connect(depotAddress, sdk.providerOrSigner); this.math = Math__factory.connect(mathAddress, sdk.providerOrSigner); this.root = Root__factory.connect(rootAddress, sdk.providerOrSigner); this.usdOracle = UsdOracle__factory.connect(usdOracleAddress, sdk.providerOrSigner); + this.junction = Junction__factory.connect(junctionAddress, sdk.providerOrSigner); const beanCrv3 = CurveMetaPool__factory.connect(beancrv3Address, sdk.providerOrSigner); const pool3 = Curve3Pool__factory.connect(pool3Address, sdk.providerOrSigner); - const tricrypto2 = CurveTriCrypto2Pool__factory.connect(tricrypto2Address, sdk.providerOrSigner); + const tricrypto2 = CurveTriCrypto2Pool__factory.connect( + tricrypto2Address, + sdk.providerOrSigner + ); const poolRegistry = CurveRegistry__factory.connect(poolRegistryAddress, sdk.providerOrSigner); const metaFactory = CurveMetaFactory__factory.connect(metaFactoryAddress, sdk.providerOrSigner); - const cryptoFactory = CurveCryptoFactory__factory.connect(cryptoFactoryAddress, sdk.providerOrSigner); + const cryptoFactory = CurveCryptoFactory__factory.connect( + cryptoFactoryAddress, + sdk.providerOrSigner + ); const zap = CurveZap__factory.connect(zapAddress, sdk.providerOrSigner); this.curve = { From 0ac01aa18313e8dd41130e9866155df0f844133e Mon Sep 17 00:00:00 2001 From: Drew Date: Mon, 4 Mar 2024 10:36:07 -0500 Subject: [PATCH 07/13] draft composition helpers. lib of templates for draft actions --- projects/sdk/src/lib/tractor/drafter.ts | 166 +++++++++++++++++------- 1 file changed, 120 insertions(+), 46 deletions(-) diff --git a/projects/sdk/src/lib/tractor/drafter.ts b/projects/sdk/src/lib/tractor/drafter.ts index 34351f17dd..7693604816 100644 --- a/projects/sdk/src/lib/tractor/drafter.ts +++ b/projects/sdk/src/lib/tractor/drafter.ts @@ -1,15 +1,24 @@ -import { ethers } from "ethers"; +import { ethers, BigNumber } from "ethers"; import { BeanstalkSDK } from "../BeanstalkSDK"; import { Clipboard } from "../depot/clipboard"; -import { Blueprint, Requisition, Draft, AdvancedFarmCall, OperatorPasteInstr } from "./types"; +import { + Blueprint, + DraftAction, + AdvancedFarmCall, + OperatorPasteInstr +} from "./types"; +import { FarmFromMode, FarmToMode } from "src/lib/farm/types"; +import { addresses } from "src/constants/addresses"; -const SELECTOR_SIZE = 4; -const SLOT_SIZE = 32; -const ARGS_START_INDEX = SELECTOR_SIZE + SLOT_SIZE; -const ADDR_SLOT_OFFSET = 12; -const PUBLISHER_COPY_INDEX = 2 ** 80 - 1; -const OPERATOR_COPY_INDEX = 2 ** 80 - 2; +const SELECTOR_SIZE = BigNumber.from(4); +const SLOT_SIZE = BigNumber.from(32); +const ARGS_START_INDEX = SELECTOR_SIZE.add(SLOT_SIZE); +const ADDR_SLOT_OFFSET = BigNumber.from(12); +const PUBLISHER_COPY_INDEX = BigNumber.from(2).pow(80).sub(1); // uint80.max; +const OPERATOR_COPY_INDEX = PUBLISHER_COPY_INDEX.sub(1); // uint80.max - 1; +const EXTERNAL_ARGS_START_INDEX = SELECTOR_SIZE.mul(2).add(SLOT_SIZE.mul(4)).add(SLOT_SIZE); +const PIPE_RETURN_BYTE_OFFSET = BigNumber.from(64); export class Drafter { static sdk: BeanstalkSDK; @@ -18,24 +27,32 @@ export class Drafter { Drafter.sdk = sdk; } - static embedDraft(blueprint: Blueprint, draft: Draft) { - blueprint.data = Drafter.encodeBlueprintData(draft.advFarmCalls); - blueprint.operatorPasteInstrs = Drafter.encodeOperatorPasteInstrs(draft.operatorPasteInstrs); + static embedDraft(blueprint: Blueprint, draft: DraftAction[]) { + let farmCalls: AdvancedFarmCall[] = []; + let operatorPasteInstrs: OperatorPasteInstr[] = []; + for (let i = 0; i < draft.length; i++) { + farmCalls.push(draft[i].farmCall); + operatorPasteInstrs.concat(draft[i].operatorPasteInstrs); + } + blueprint.data = Drafter.encodeBlueprintData(farmCalls); + blueprint.operatorPasteInstrs = Drafter.encodeOperatorPasteInstrs(operatorPasteInstrs); } - static concatDrafts(firstDraft: Draft, secondDraft: Draft): Draft { - let draft = {}; - draft.advFarmCalls = firstDraft.advFarmCalls.concat(secondDraft.advFarmCalls); - draft.operatorPasteInstrs = firstDraft.operatorPasteInstrs.concat( - secondDraft.operatorPasteInstrs - ); - return draft; - } + // static concatDrafts(firstDraft: Draft, secondDraft: Draft): Draft { + // let draft = {}; + // draft.farmCalls = firstDraft.farmCalls.concat(secondDraft.farmCalls); + // draft.operatorPasteInstrs = firstDraft.operatorPasteInstrs.concat( + // secondDraft.operatorPasteInstrs + // ); + // return draft; + // } // encodeAdvancedFarmCalls static encodeBlueprintData(calls: AdvancedFarmCall[]): ethers.Bytes { // sdk.contracts.farmFacet.interface.encodeFunctionData("advancedFarm", [ - return Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("advancedFarm", [calls]); + return ethers.utils.arrayify( + Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("advancedFarm", [calls]) + ); } // static decodeBlueprintData @@ -60,9 +77,9 @@ export class Drafter { throw TypeError("OperatorPasteInstr must be 32 bytes"); } return { - copyByteIndex: ethers.BigNumber.from(ethers.utils.hexDataSlice(instr, 0, 9)).toNumber(), - pasteCallIndex: ethers.BigNumber.from(ethers.utils.hexDataSlice(instr, 10, 19)).toNumber(), - pasteByteIndex: ethers.BigNumber.from(ethers.utils.hexDataSlice(instr, 20, 29)).toNumber() + copyByteIndex: BigNumber.from(ethers.utils.hexDataSlice(instr, 0, 9)), + pasteCallIndex: BigNumber.from(ethers.utils.hexDataSlice(instr, 10, 19)), + pasteByteIndex: BigNumber.from(ethers.utils.hexDataSlice(instr, 20, 29)) }; // encodeLibReturnPasteParam(returnDataItemIndex : uint80, copyByteIndex: uint80, pasteByteIndex: uint80): (bytes32) {} @@ -71,49 +88,106 @@ export class Drafter { // decodeClipboard(clipboard : Clipboard): (bytes1, uint256, bytes32[]) {} } - static balanceOfStalkDraft(callIndex: number): Draft { + static balanceOfStalkDraft(callIndex: number): DraftAction { return { - advFarmCalls: [ - { - callData: Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("balanceOfStalk", [ - ethers.constants.AddressZero - ]), - clipboard: ethers.utils.arrayify("0x000000") - } - ], + farmCall: { + callData: Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("balanceOfStalk", [ + ethers.constants.AddressZero + ]), + clipboard: "0x000000" + }, operatorPasteInstrs: [ { copyByteIndex: PUBLISHER_COPY_INDEX, - pasteCallIndex: callIndex, + pasteCallIndex: BigNumber.from(callIndex), pasteByteIndex: ARGS_START_INDEX } ] }; } - static mowDraft(callIndex: number): Draft { + static mowDraft(callIndex: number): DraftAction { return { - advFarmCalls: [ - { - callData: Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("mow", [ - ethers.constants.AddressZero, - ethers.constants.AddressZero - ]), - clipboard: ethers.utils.arrayify("0x000000") - } - ], + farmCall: { + callData: Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("mow", [ + ethers.constants.AddressZero, + ethers.constants.AddressZero + ]), + clipboard: "0x000000" + }, operatorPasteInstrs: [ { copyByteIndex: PUBLISHER_COPY_INDEX, - pasteCallIndex: callIndex, + pasteCallIndex: BigNumber.from(callIndex), pasteByteIndex: ARGS_START_INDEX }, { copyByteIndex: PUBLISHER_COPY_INDEX, - pasteCallIndex: callIndex, - pasteByteIndex: ARGS_START_INDEX + SLOT_SIZE + pasteCallIndex: BigNumber.from(callIndex), + pasteByteIndex: ARGS_START_INDEX.add(SLOT_SIZE) } ] }; } + + static subReturnsDraft( + leftReturnDataIndex: number, + rightReturnDataIndex: number, + leftCopyIndex: number = 0, + rightCopyIndex: number = 0 + ): DraftAction { + return { + farmCall: { + callData: Drafter.sdk.contracts.junction.interface.encodeFunctionData("sub", [0, 0]), + clipboard: Clipboard.encode([ + [leftReturnDataIndex, leftCopyIndex, EXTERNAL_ARGS_START_INDEX.toNumber()], + [ + rightReturnDataIndex, + rightCopyIndex, + EXTERNAL_ARGS_START_INDEX.add(SLOT_SIZE).toNumber() + ] + ]) + }, + operatorPasteInstrs: [] + }; + } + + static scaleReturnDraft( + returnDataIndex: number, + mul: BigNumber, + div: BigNumber, + copyIndex: number = 0 + ): DraftAction { + return { + farmCall: { + callData: Drafter.sdk.contracts.junction.interface.encodeFunctionData("muldiv", [ + 0, + mul, + div + ]), + clipboard: Clipboard.encode([ + [returnDataIndex, copyIndex, EXTERNAL_ARGS_START_INDEX.toNumber()] + ]) + }, + operatorPasteInstrs: [] + }; + } + + static transferBeansReturnDraft(returnDataIndex: number, copyIndex: number = 0): DraftAction { + return { + farmCall: { + callData: Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("transferToken", [ + addresses.BEAN, + ethers.constants.AddressZero, + 0, + FarmFromMode.EXTERNAL, + FarmToMode.EXTERNAL + ]), + clipboard: Clipboard.encode([ + [returnDataIndex, copyIndex, EXTERNAL_ARGS_START_INDEX.add(SLOT_SIZE.mul(2)).toNumber()] + ]) + }, + operatorPasteInstrs: [] + }; + } } From 66cbf37b9ee39c27633885316243b50369ecc6b6 Mon Sep 17 00:00:00 2001 From: Drew Date: Mon, 4 Mar 2024 10:36:28 -0500 Subject: [PATCH 08/13] one example of how a full mow blueprint might look. not a standard --- projects/sdk/src/lib/tractor/examples.ts | 30 ++++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/projects/sdk/src/lib/tractor/examples.ts b/projects/sdk/src/lib/tractor/examples.ts index d61e2a1a3d..5627088884 100644 --- a/projects/sdk/src/lib/tractor/examples.ts +++ b/projects/sdk/src/lib/tractor/examples.ts @@ -1,19 +1,17 @@ // This test uses the Tractor SDK and core Tractor code. It represents how an end user would interact with Tractor. import { ethers } from "ethers"; -import { - AdvancedFarmCall, - Blueprint, - Draft, - OperatorPasteInstr, - encodeBlueprintData, - encodeOperatorPasteInstrs -} from "./types"; +import { Blueprint, DraftAction } from "./types"; import { Drafter } from "./drafter"; +// TODO use whatever SDK standard is. +const RATIO_FACTOR = ethers.BigNumber.from(10).pow(18); + // Create a Blueprint to Mow the publishers stalk. // This function represents only one approach to implement a Mow Blueprint and is inherently biased. function createBlueprint_mow(publisher: string) { + const rewardRatio = RATIO_FACTOR.div(100); // 1% + const blueprint: Blueprint = { publisher: publisher, maxNonce: ethers.constants.MaxUint256, @@ -21,13 +19,15 @@ function createBlueprint_mow(publisher: string) { endTime: ethers.constants.MaxUint256 }; - let draft: Draft; - - draft = Drafter.balanceOfStalkDraft(0); - draft = Drafter.concatDrafts(draft, Drafter.mowDraft(1)); - draft = Drafter.concatDrafts(draft, Drafter.balanceOfStalkDraft(2)); - draft = // need to use clipboard + // Sequence of actions. + let draft: DraftAction[] = []; + draft.push(Drafter.balanceOfStalkDraft(0)); + draft.push(Drafter.mowDraft(1)); + draft.push(Drafter.balanceOfStalkDraft(2)); + draft.push(Drafter.subReturnsDraft(2, 0)); + draft.push(Drafter.scaleReturnDraft(3, rewardRatio, RATIO_FACTOR)); + draft.push(Drafter.transferBeansReturnDraft(4)); - Drafter.embedDraft(blueprint, encodeBlueprintData(blueprint, draft)); + Drafter.embedDraft(blueprint, draft); return blueprint; } From 218f22e281030e3c46dd9a8430cfee7257c147ee Mon Sep 17 00:00:00 2001 From: Drew Date: Mon, 4 Mar 2024 16:10:32 -0500 Subject: [PATCH 09/13] mow full test. non compiled --- projects/sdk/src/lib/tractor/examples.ts | 2 +- projects/sdk/src/lib/tractor/tractor.test.ts | 24 +++++++++++++++++++ projects/sdk/src/lib/tractor/tractor.ts | 25 +++++++++++++++++--- projects/sdk/src/lib/tractor/types.ts | 18 ++++++++------ 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/projects/sdk/src/lib/tractor/examples.ts b/projects/sdk/src/lib/tractor/examples.ts index 5627088884..19b7bcd7c5 100644 --- a/projects/sdk/src/lib/tractor/examples.ts +++ b/projects/sdk/src/lib/tractor/examples.ts @@ -9,7 +9,7 @@ const RATIO_FACTOR = ethers.BigNumber.from(10).pow(18); // Create a Blueprint to Mow the publishers stalk. // This function represents only one approach to implement a Mow Blueprint and is inherently biased. -function createBlueprint_mow(publisher: string) { +export function createBlueprint_mow(publisher: string) { const rewardRatio = RATIO_FACTOR.div(100); // 1% const blueprint: Blueprint = { diff --git a/projects/sdk/src/lib/tractor/tractor.test.ts b/projects/sdk/src/lib/tractor/tractor.test.ts index e69de29bb2..6f5e317b7f 100644 --- a/projects/sdk/src/lib/tractor/tractor.test.ts +++ b/projects/sdk/src/lib/tractor/tractor.test.ts @@ -0,0 +1,24 @@ +// This test uses the Tractor SDK and core Tractor code. It represents how an end user would interact with Tractor. + +import { ethers } from "ethers"; +import { Blueprint, Requisition } from "./types"; +import { createBlueprint_mow } from "./examples"; +import { Tractor } from "./tractor"; +import { getTestUtils } from "src/utils/TestUtils/provider"; + +const { sdk, account, utils } = getTestUtils(); + +describe("tractor mow", async () => { + it("throws if tractor operate fails", async () => { + let publisher: ethers.Wallet = ethers.Wallet.createRandom(); + const blueprint: Blueprint = createBlueprint_mow(publisher.address); + const blueprintHash: string = await Tractor.getBlueprintHash(blueprint); + const requisition: Requisition = { + blueprint: blueprint, + blueprintHash: blueprintHash, + signature: await publisher.signMessage(blueprintHash) + }; + + await sdk.contracts.beanstalk.runBlueprint(requisition).then((txn) => txn.wait()); + }); +}); diff --git a/projects/sdk/src/lib/tractor/tractor.ts b/projects/sdk/src/lib/tractor/tractor.ts index 2b752f7c9a..5fe5be2948 100644 --- a/projects/sdk/src/lib/tractor/tractor.ts +++ b/projects/sdk/src/lib/tractor/tractor.ts @@ -1,6 +1,6 @@ import { BeanstalkSDK } from "../BeanstalkSDK"; import { ethers, ContractTransaction } from "ethers"; -import { Requisition, Bytes } from "./types"; +import { Blueprint, Requisition } from "./types"; export class Tractor { static sdk: BeanstalkSDK; @@ -9,7 +9,6 @@ export class Tractor { // operator: Operator; // sequenceBuilder: OperatorDataBuilder; - constructor(sdk: BeanstalkSDK) { Tractor.sdk = sdk; // this.sequenceBuilder = new SequenceBuilder(sdk); @@ -17,8 +16,28 @@ export class Tractor { // this.publisher = new Publisher(sdk); } + static async getBlueprintHash(blueprint: Blueprint): Promise { + return Tractor.sdk.contracts.beanstalk.interface.getBlueprintHash(blueprint); + } + + // async signRequisition(requisition: Requisition, signer: ethers.Signer) { + // // Ethers treats hash as an unexpectedly encoded string, whereas solidity signs hash as bytes. So arrayify here. + // requisition.signature = await signer.signMessage( + // ethers.utils.arrayify(requisition.blueprintHash) + // ); + // } + + // async composeBlueprintData() {} + + // async composeBlueprintOperatorPasteInstrs() {} + + // async encodeData() {} + + // encode; + + // async encodeOperatorData() {} + async tractor(requisition: Requisition, operatorData: Bytes): Promise { return Tractor.sdk.contracts.beanstalk.tractor(requisition, operatorData); } - } diff --git a/projects/sdk/src/lib/tractor/types.ts b/projects/sdk/src/lib/tractor/types.ts index 25f3931c2b..263c3c0e00 100644 --- a/projects/sdk/src/lib/tractor/types.ts +++ b/projects/sdk/src/lib/tractor/types.ts @@ -1,11 +1,11 @@ import { ethers } from "ethers"; -export type uint80 = number; +export type uint80 = ethers.BigNumber; export type Blueprint = { publisher: string; data: ethers.Bytes; - operatorPasteInstrs?: ethers.Bytes; + operatorPasteInstrs: ethers.Bytes; maxNonce: ethers.BigNumber; startTime: ethers.BigNumber; endTime: ethers.BigNumber; @@ -13,18 +13,22 @@ export type Blueprint = { export type Requisition = { blueprint: Blueprint; - blueprintHash: ethers.Bytes; - signature: ethers.Bytes; + blueprintHash: string; + signature: string; }; -export type Draft = { - advFarmCalls: AdvancedFarmCall[]; +// export type Draft = { +// actions: DraftAction[]; +// }; + +export type DraftAction = { + farmCall: AdvancedFarmCall; operatorPasteInstrs: OperatorPasteInstr[]; }; export type AdvancedFarmCall = { callData: ethers.Bytes; - clipboard: ethers.Bytes; + clipboard: string; }; export type OperatorPasteInstr = { From 5edae4353c3a0ad0ac8a106f92c80c9ae4e8d2c9 Mon Sep 17 00:00:00 2001 From: Drew Date: Mon, 4 Mar 2024 18:13:24 -0500 Subject: [PATCH 10/13] fix contract calls --- projects/sdk/src/lib/tractor/drafter.ts | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/projects/sdk/src/lib/tractor/drafter.ts b/projects/sdk/src/lib/tractor/drafter.ts index 7693604816..2bfd37fd5c 100644 --- a/projects/sdk/src/lib/tractor/drafter.ts +++ b/projects/sdk/src/lib/tractor/drafter.ts @@ -2,12 +2,7 @@ import { ethers, BigNumber } from "ethers"; import { BeanstalkSDK } from "../BeanstalkSDK"; import { Clipboard } from "../depot/clipboard"; -import { - Blueprint, - DraftAction, - AdvancedFarmCall, - OperatorPasteInstr -} from "./types"; +import { Blueprint, DraftAction, AdvancedFarmCall, OperatorPasteInstr } from "./types"; import { FarmFromMode, FarmToMode } from "src/lib/farm/types"; import { addresses } from "src/constants/addresses"; @@ -57,8 +52,8 @@ export class Drafter { // static decodeBlueprintData - static encodeOperatorPasteInstrs(instrs: OperatorPasteInstr[]): ethers.Bytes { - return ethers.utils.concat(instrs.map((instr) => Drafter.encodeOperatorPasteInstr(instr))); + static encodeOperatorPasteInstrs(instrs: OperatorPasteInstr[]): ethers.Bytes[] { + return instrs.map((instr) => Drafter.encodeOperatorPasteInstr(instr)); } // Returns Bytes32 @@ -160,7 +155,7 @@ export class Drafter { ): DraftAction { return { farmCall: { - callData: Drafter.sdk.contracts.junction.interface.encodeFunctionData("muldiv", [ + callData: Drafter.sdk.contracts.junction.interface.encodeFunctionData("mulDiv", [ 0, mul, div @@ -177,11 +172,11 @@ export class Drafter { return { farmCall: { callData: Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("transferToken", [ - addresses.BEAN, + addresses.BEAN.toString(), ethers.constants.AddressZero, 0, - FarmFromMode.EXTERNAL, - FarmToMode.EXTERNAL + 0, // EXTERNAL + 0 // EXTERNAL ]), clipboard: Clipboard.encode([ [returnDataIndex, copyIndex, EXTERNAL_ARGS_START_INDEX.add(SLOT_SIZE.mul(2)).toNumber()] From 23cc9d1600ee8b6ec01729a80bc87dc917954b5d Mon Sep 17 00:00:00 2001 From: Drew Date: Mon, 4 Mar 2024 18:14:07 -0500 Subject: [PATCH 11/13] fix typings, cleanup --- .../sdk/src/lib/tractor/OperatorPasteInstrs.ts | 16 ---------------- projects/sdk/src/lib/tractor/tractor.test.ts | 4 +++- projects/sdk/src/lib/tractor/tractor.ts | 7 +++++-- projects/sdk/src/lib/tractor/types.ts | 4 ++-- 4 files changed, 10 insertions(+), 21 deletions(-) delete mode 100644 projects/sdk/src/lib/tractor/OperatorPasteInstrs.ts diff --git a/projects/sdk/src/lib/tractor/OperatorPasteInstrs.ts b/projects/sdk/src/lib/tractor/OperatorPasteInstrs.ts deleted file mode 100644 index 3d3b0e974a..0000000000 --- a/projects/sdk/src/lib/tractor/OperatorPasteInstrs.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { BeanstalkSDK } from "../BeanstalkSDK"; -import { uint80, Bytes32 } from "./types"; - -export class OperatorPasteInstrs { - static sdk: BeanstalkSDK; - - constructor(sdk: BeanstalkSDK) { - OperatorPasteInstrs.sdk = sdk; - } - - encode(copyByteIndex: uint80, pasteCallIndex: uint80, pasteByteIndex: uint80): Bytes32 { return ''; } - - decode(operatorPasteInstr: Bytes32): [uint80, uint80, uint80] { return ['', '', ''] } - - -} diff --git a/projects/sdk/src/lib/tractor/tractor.test.ts b/projects/sdk/src/lib/tractor/tractor.test.ts index 6f5e317b7f..be470a44db 100644 --- a/projects/sdk/src/lib/tractor/tractor.test.ts +++ b/projects/sdk/src/lib/tractor/tractor.test.ts @@ -19,6 +19,8 @@ describe("tractor mow", async () => { signature: await publisher.signMessage(blueprintHash) }; - await sdk.contracts.beanstalk.runBlueprint(requisition).then((txn) => txn.wait()); + const operatorData: ethers.Bytes = ethers.utils.arrayify(""); + + await sdk.contracts.beanstalk.tractor(requisition, operatorData).then((txn) => txn.wait()); }); }); diff --git a/projects/sdk/src/lib/tractor/tractor.ts b/projects/sdk/src/lib/tractor/tractor.ts index 5fe5be2948..4f3cd0e5af 100644 --- a/projects/sdk/src/lib/tractor/tractor.ts +++ b/projects/sdk/src/lib/tractor/tractor.ts @@ -17,7 +17,7 @@ export class Tractor { } static async getBlueprintHash(blueprint: Blueprint): Promise { - return Tractor.sdk.contracts.beanstalk.interface.getBlueprintHash(blueprint); + return Tractor.sdk.contracts.beanstalk.getBlueprintHash(blueprint); } // async signRequisition(requisition: Requisition, signer: ethers.Signer) { @@ -37,7 +37,10 @@ export class Tractor { // async encodeOperatorData() {} - async tractor(requisition: Requisition, operatorData: Bytes): Promise { + async tractor( + requisition: Requisition, + operatorData: ethers.Bytes + ): Promise { return Tractor.sdk.contracts.beanstalk.tractor(requisition, operatorData); } } diff --git a/projects/sdk/src/lib/tractor/types.ts b/projects/sdk/src/lib/tractor/types.ts index 263c3c0e00..48feb35186 100644 --- a/projects/sdk/src/lib/tractor/types.ts +++ b/projects/sdk/src/lib/tractor/types.ts @@ -5,7 +5,7 @@ export type uint80 = ethers.BigNumber; export type Blueprint = { publisher: string; data: ethers.Bytes; - operatorPasteInstrs: ethers.Bytes; + operatorPasteInstrs: ethers.Bytes[]; maxNonce: ethers.BigNumber; startTime: ethers.BigNumber; endTime: ethers.BigNumber; @@ -27,7 +27,7 @@ export type DraftAction = { }; export type AdvancedFarmCall = { - callData: ethers.Bytes; + callData: string; clipboard: string; }; From d4ef892c0010ce701e92e26706e056012a0e5f44 Mon Sep 17 00:00:00 2001 From: Drew Date: Wed, 6 Mar 2024 11:25:33 -0500 Subject: [PATCH 12/13] deployment, reset, and test scripts for tractor sdk using not-yet-existing contracts --- package.json | 2 ++ projects/sdk/src/constants/addresses.ts | 1 + protocol/hardhat.config.js | 29 +++++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/package.json b/package.json index 7a70051cd8..b26639fc99 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "sdk:dev": "yarn workspace @beanstalk/sdk dev", "sdk:build": "yarn workspace @beanstalk/sdk build", "sdk:test": "jest --selectProjects sdk --silent --runInBand --", + "sdk:tractor:reset": "cd protocol; npx hardhat tractor_sdk_test_init --network localhost; cd ..;", + "sdk:tractor:test": "yarn sdk:test -t 'tractor' --network localhost --verbose", "sdk-wells:test": "jest --selectProjects sdk-wells --runInBand --silent=false --", "sdk-wells:test:watch": "jest --selectProjects sdk-wells --runInBand --watch --verbose true --", "sdk:testdev": "jest --selectProjects sdk --watch --runInBand --", diff --git a/projects/sdk/src/constants/addresses.ts b/projects/sdk/src/constants/addresses.ts index 4329c267df..d1094cc1dc 100644 --- a/projects/sdk/src/constants/addresses.ts +++ b/projects/sdk/src/constants/addresses.ts @@ -16,6 +16,7 @@ export const addresses = { PIPELINE: Address.make("0xb1bE0000C6B3C62749b5F0c92480146452D15423"), ROOT: Address.make("0x77700005BEA4DE0A78b956517f099260C2CA9a26"), USD_ORACLE: Address.make("0x1aa19ed7DfC555E4644c9353Ad383c33024855F7"), + JUNCTION: Address.make("0x0f88D35a40bCF9FbE024DBB5df4e4504086336b0"), // ---------------------------------------- // BeaNFT Contracts diff --git a/protocol/hardhat.config.js b/protocol/hardhat.config.js index 14c5244eb0..6fd60b88dd 100644 --- a/protocol/hardhat.config.js +++ b/protocol/hardhat.config.js @@ -188,6 +188,35 @@ task("diamondABI", "Generates ABI file for diamond, includes all ABIs of facets" console.log("ABI written to abi/Beanstalk.json"); }); +// Used for testing Tractor. +task("tractor_sdk_test_init", async function () { + await network.provider.request({ + method: "hardhat_reset", + params: [ + { + forking: { + jsonRpcUrl: process.env.FORKING_RPC, + blockNumber: parseInt(process.env.BLOCK_NUMBER), + }, + }, + ], + }); + + const owner = await impersonateBeanstalkOwner(); + await mintEth(owner.address); + await upgradeWithNewFacets({ + diamondAddress: BEANSTALK, + facetNames: ["TractorFacet"], + bip: false, + verbose: false, + account: owner + }); + console.log("TractorFacet cut"); + + const tractor = await ethers.deployContract("Junction", [], owner); + console.log("Junctions deployed to ", tractor.address); +}); + task("marketplace", async function () { const owner = await impersonateBeanstalkOwner(); await mintEth(owner.address); From 242ff67c5e674a37ff1fc6696ddad2478680db7e Mon Sep 17 00:00:00 2001 From: Drew Date: Wed, 6 Mar 2024 11:29:08 -0500 Subject: [PATCH 13/13] update to tractor tests. compiling, running. fail on tractor operation. --- projects/sdk/src/constants/addresses.ts | 1 + projects/sdk/src/lib/BeanstalkSDK.ts | 6 ++++ projects/sdk/src/lib/tractor/drafter.ts | 32 ++++++++++---------- projects/sdk/src/lib/tractor/examples.ts | 18 +++++------ projects/sdk/src/lib/tractor/tractor.test.ts | 25 +++++++++++---- projects/sdk/src/lib/tractor/tractor.ts | 2 +- protocol/test/utils/tractor.js | 21 ------------- 7 files changed, 52 insertions(+), 53 deletions(-) diff --git a/projects/sdk/src/constants/addresses.ts b/projects/sdk/src/constants/addresses.ts index d1094cc1dc..19fb1fec46 100644 --- a/projects/sdk/src/constants/addresses.ts +++ b/projects/sdk/src/constants/addresses.ts @@ -16,6 +16,7 @@ export const addresses = { PIPELINE: Address.make("0xb1bE0000C6B3C62749b5F0c92480146452D15423"), ROOT: Address.make("0x77700005BEA4DE0A78b956517f099260C2CA9a26"), USD_ORACLE: Address.make("0x1aa19ed7DfC555E4644c9353Ad383c33024855F7"), + // TODO: Update with mainnet deployed address. JUNCTION: Address.make("0x0f88D35a40bCF9FbE024DBB5df4e4504086336b0"), // ---------------------------------------- diff --git a/projects/sdk/src/lib/BeanstalkSDK.ts b/projects/sdk/src/lib/BeanstalkSDK.ts index f75fa8580f..dcc8ca12e0 100644 --- a/projects/sdk/src/lib/BeanstalkSDK.ts +++ b/projects/sdk/src/lib/BeanstalkSDK.ts @@ -12,6 +12,8 @@ import { Permit } from "./permit"; import { Root } from "./root"; import { Sdk as Queries, getSdk as getQueries } from "../constants/generated-gql/graphql"; import { Swap } from "src/lib/swap/Swap"; +import { Tractor } from "src/lib/tractor/tractor"; +import { Drafter } from "src/lib/tractor/drafter"; import { Bean } from "./bean"; import { Pools } from "./pools"; import defaultSettings from "src/defaultSettings.json"; @@ -60,6 +62,8 @@ export class BeanstalkSDK { public readonly permit: Permit; public readonly root: Root; public readonly swap: Swap; + public readonly tractor: Tractor; + public readonly drafter: Drafter; public readonly bean: Bean; public readonly wells: WellsSDK; @@ -92,6 +96,8 @@ export class BeanstalkSDK { // Ecosystem this.root = new Root(this); this.swap = new Swap(this); + this.tractor = new Tractor(this); + this.drafter = new Drafter(this); // Wells this.wells = new WellsSDK(config); diff --git a/projects/sdk/src/lib/tractor/drafter.ts b/projects/sdk/src/lib/tractor/drafter.ts index 2bfd37fd5c..8515d79c75 100644 --- a/projects/sdk/src/lib/tractor/drafter.ts +++ b/projects/sdk/src/lib/tractor/drafter.ts @@ -22,18 +22,18 @@ export class Drafter { Drafter.sdk = sdk; } - static embedDraft(blueprint: Blueprint, draft: DraftAction[]) { + embedDraft(blueprint: Blueprint, draft: DraftAction[]) { let farmCalls: AdvancedFarmCall[] = []; let operatorPasteInstrs: OperatorPasteInstr[] = []; for (let i = 0; i < draft.length; i++) { farmCalls.push(draft[i].farmCall); operatorPasteInstrs.concat(draft[i].operatorPasteInstrs); } - blueprint.data = Drafter.encodeBlueprintData(farmCalls); - blueprint.operatorPasteInstrs = Drafter.encodeOperatorPasteInstrs(operatorPasteInstrs); + blueprint.data = this.encodeBlueprintData(farmCalls); + blueprint.operatorPasteInstrs = this.encodeOperatorPasteInstrs(operatorPasteInstrs); } - // static concatDrafts(firstDraft: Draft, secondDraft: Draft): Draft { + // concatDrafts(firstDraft: Draft, secondDraft: Draft): Draft { // let draft = {}; // draft.farmCalls = firstDraft.farmCalls.concat(secondDraft.farmCalls); // draft.operatorPasteInstrs = firstDraft.operatorPasteInstrs.concat( @@ -43,21 +43,21 @@ export class Drafter { // } // encodeAdvancedFarmCalls - static encodeBlueprintData(calls: AdvancedFarmCall[]): ethers.Bytes { + encodeBlueprintData(calls: AdvancedFarmCall[]): ethers.Bytes { // sdk.contracts.farmFacet.interface.encodeFunctionData("advancedFarm", [ return ethers.utils.arrayify( Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("advancedFarm", [calls]) ); } - // static decodeBlueprintData + // decodeBlueprintData - static encodeOperatorPasteInstrs(instrs: OperatorPasteInstr[]): ethers.Bytes[] { - return instrs.map((instr) => Drafter.encodeOperatorPasteInstr(instr)); + encodeOperatorPasteInstrs(instrs: OperatorPasteInstr[]): ethers.Bytes[] { + return instrs.map((instr) => this.encodeOperatorPasteInstr(instr)); } // Returns Bytes32 - static encodeOperatorPasteInstr(instr: OperatorPasteInstr): ethers.Bytes { + encodeOperatorPasteInstr(instr: OperatorPasteInstr): ethers.Bytes { return ethers.utils.concat([ ethers.utils.zeroPad(ethers.utils.hexValue(instr.copyByteIndex), 10), ethers.utils.zeroPad(ethers.utils.hexValue(instr.copyByteIndex), 10), @@ -66,7 +66,7 @@ export class Drafter { ]); } - static decodeOperatorPasteInstr(instr: ethers.Bytes): OperatorPasteInstr { + decodeOperatorPasteInstr(instr: ethers.Bytes): OperatorPasteInstr { // const instrBytes: ethers.Bytes = ethers.utils.arrayify(instr); if (instr.length != 32) { throw TypeError("OperatorPasteInstr must be 32 bytes"); @@ -83,7 +83,7 @@ export class Drafter { // decodeClipboard(clipboard : Clipboard): (bytes1, uint256, bytes32[]) {} } - static balanceOfStalkDraft(callIndex: number): DraftAction { + balanceOfStalkDraft(callIndex: number): DraftAction { return { farmCall: { callData: Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("balanceOfStalk", [ @@ -101,7 +101,7 @@ export class Drafter { }; } - static mowDraft(callIndex: number): DraftAction { + mowDraft(callIndex: number): DraftAction { return { farmCall: { callData: Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("mow", [ @@ -125,7 +125,7 @@ export class Drafter { }; } - static subReturnsDraft( + subReturnsDraft( leftReturnDataIndex: number, rightReturnDataIndex: number, leftCopyIndex: number = 0, @@ -147,7 +147,7 @@ export class Drafter { }; } - static scaleReturnDraft( + scaleReturnDraft( returnDataIndex: number, mul: BigNumber, div: BigNumber, @@ -168,11 +168,11 @@ export class Drafter { }; } - static transferBeansReturnDraft(returnDataIndex: number, copyIndex: number = 0): DraftAction { + transferBeansReturnDraft(returnDataIndex: number, copyIndex: number = 0): DraftAction { return { farmCall: { callData: Drafter.sdk.contracts.beanstalk.interface.encodeFunctionData("transferToken", [ - addresses.BEAN.toString(), + addresses.BEAN.get(Drafter.sdk.chainId), ethers.constants.AddressZero, 0, 0, // EXTERNAL diff --git a/projects/sdk/src/lib/tractor/examples.ts b/projects/sdk/src/lib/tractor/examples.ts index 19b7bcd7c5..d15d154c1c 100644 --- a/projects/sdk/src/lib/tractor/examples.ts +++ b/projects/sdk/src/lib/tractor/examples.ts @@ -2,14 +2,14 @@ import { ethers } from "ethers"; import { Blueprint, DraftAction } from "./types"; -import { Drafter } from "./drafter"; +import { BeanstalkSDK } from "../BeanstalkSDK"; // TODO use whatever SDK standard is. const RATIO_FACTOR = ethers.BigNumber.from(10).pow(18); // Create a Blueprint to Mow the publishers stalk. // This function represents only one approach to implement a Mow Blueprint and is inherently biased. -export function createBlueprint_mow(publisher: string) { +export function createBlueprint_mow(sdk: BeanstalkSDK, publisher: string) { const rewardRatio = RATIO_FACTOR.div(100); // 1% const blueprint: Blueprint = { @@ -21,13 +21,13 @@ export function createBlueprint_mow(publisher: string) { // Sequence of actions. let draft: DraftAction[] = []; - draft.push(Drafter.balanceOfStalkDraft(0)); - draft.push(Drafter.mowDraft(1)); - draft.push(Drafter.balanceOfStalkDraft(2)); - draft.push(Drafter.subReturnsDraft(2, 0)); - draft.push(Drafter.scaleReturnDraft(3, rewardRatio, RATIO_FACTOR)); - draft.push(Drafter.transferBeansReturnDraft(4)); + draft.push(sdk.drafter.balanceOfStalkDraft(0)); + draft.push(sdk.drafter.mowDraft(1)); + draft.push(sdk.drafter.balanceOfStalkDraft(2)); + draft.push(sdk.drafter.subReturnsDraft(2, 0)); + draft.push(sdk.drafter.scaleReturnDraft(3, rewardRatio, RATIO_FACTOR)); + draft.push(sdk.drafter.transferBeansReturnDraft(4)); - Drafter.embedDraft(blueprint, draft); + sdk.drafter.embedDraft(blueprint, draft); return blueprint; } diff --git a/projects/sdk/src/lib/tractor/tractor.test.ts b/projects/sdk/src/lib/tractor/tractor.test.ts index be470a44db..e8a16e4de8 100644 --- a/projects/sdk/src/lib/tractor/tractor.test.ts +++ b/projects/sdk/src/lib/tractor/tractor.test.ts @@ -3,24 +3,37 @@ import { ethers } from "ethers"; import { Blueprint, Requisition } from "./types"; import { createBlueprint_mow } from "./examples"; -import { Tractor } from "./tractor"; +import { addresses } from "src/constants"; import { getTestUtils } from "src/utils/TestUtils/provider"; const { sdk, account, utils } = getTestUtils(); +jest.setTimeout(30 * 1000); + +describe("tractor mow", () => { + beforeAll(async function () { + // Ensure contract deployment. + // TODO TEMP remove this once mainnet deployment. + expect( + (await sdk.provider.getCode(addresses.JUNCTION.get(sdk.chainId))).length + ).toBeGreaterThan(2); + + await utils.setETHBalance(account, sdk.tokens.ETH.amount(10)); + }); -describe("tractor mow", async () => { it("throws if tractor operate fails", async () => { let publisher: ethers.Wallet = ethers.Wallet.createRandom(); - const blueprint: Blueprint = createBlueprint_mow(publisher.address); - const blueprintHash: string = await Tractor.getBlueprintHash(blueprint); + const blueprint: Blueprint = createBlueprint_mow(sdk, publisher.address); + const blueprintHash: string = await sdk.tractor.getBlueprintHash(blueprint); const requisition: Requisition = { blueprint: blueprint, blueprintHash: blueprintHash, signature: await publisher.signMessage(blueprintHash) }; - const operatorData: ethers.Bytes = ethers.utils.arrayify(""); + const operatorData: ethers.Bytes = ethers.utils.arrayify("0x"); - await sdk.contracts.beanstalk.tractor(requisition, operatorData).then((txn) => txn.wait()); + await sdk.contracts.beanstalk + .tractor(requisition, operatorData, { gasLimit: 1_000_000 }) + .then((txn) => txn.wait()); }); }); diff --git a/projects/sdk/src/lib/tractor/tractor.ts b/projects/sdk/src/lib/tractor/tractor.ts index 4f3cd0e5af..e5649d5919 100644 --- a/projects/sdk/src/lib/tractor/tractor.ts +++ b/projects/sdk/src/lib/tractor/tractor.ts @@ -16,7 +16,7 @@ export class Tractor { // this.publisher = new Publisher(sdk); } - static async getBlueprintHash(blueprint: Blueprint): Promise { + async getBlueprintHash(blueprint: Blueprint): Promise { return Tractor.sdk.contracts.beanstalk.getBlueprintHash(blueprint); } diff --git a/protocol/test/utils/tractor.js b/protocol/test/utils/tractor.js index f7c745e07a..329c29da90 100644 --- a/protocol/test/utils/tractor.js +++ b/protocol/test/utils/tractor.js @@ -77,15 +77,6 @@ const signRequisition = async (requisition, signer) => { ); }; -const getNormalBlueprintData = (data) => { - const blueprintData = ethers.utils.defaultAbiCoder.encode(["bytes[]"], [data]); - return ethers.utils.hexlify(new Uint8Array([0, ...ethers.utils.arrayify(blueprintData)])); -}; - -const getAdvancedBlueprintData = (data) => { - const blueprintData = ethers.utils.defaultAbiCoder.encode(["(bytes,bytes)[]"], [data]); - return ethers.utils.hexlify(new Uint8Array([1, ...ethers.utils.arrayify(blueprintData)])); -}; const generateCalldataCopyParams = (info) => { return info.map(([copyIndex, pasteIndex, length]) => { @@ -105,17 +96,6 @@ const generateCalldataCopyParams = (info) => { }); }; -const encodeBlueprintData = async (advancedFarmCalls) => { - return ethers.utils.solidityPack( - ["bytes1", "bytes"], - [ - 0, // data type - (await farmFacetInterface()).encodeFunctionData("advancedFarm", [advancedFarmCalls]) - // await farmFacetInterface().then((interface) => { interface.encodeFunctionData("advancedFarm", [advancedFarmCalls]) }) - ] - ); -}; - // Shape: // 4 bytes (pipe selector) // 32 bytes (location of PipeCall) @@ -921,7 +901,6 @@ module.exports = { getNormalBlueprintData, getAdvancedBlueprintData, generateCalldataCopyParams, - encodeBlueprintData, draftDepositInternalBeanBalance, draftMow, draftPlant,