Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

chore: fix some typos in comment #2041

Merged
merged 4 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/handler.publish-pr-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
- name: Download artifact
continue-on-error: true
id: download_artifact
uses: dawidd6/action-download-artifact@v4
uses: dawidd6/action-download-artifact@v6
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
workflow_conclusion: success
Expand Down
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
# test utilities
lcov
actionlint
git
];

# solidity dev inputs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ interface IVestingScheduler {
* @param superToken SuperToken to be vested
* @param receiver Vesting receiver
* @param startDate Timestamp when the vesting should start
* @param cliffDate Timestamp of cliff exectution - if 0, startDate acts as cliff
* @param cliffDate Timestamp of cliff execution - if 0, startDate acts as cliff
* @param flowRate The flowRate for the stream
* @param cliffAmount The amount to be transferred at the cliff
* @param endDate The timestamp when the stream should stop.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ interface IVestingSchedulerV2 {
* @param receiver Vesting receiver
* @param startDate Timestamp when the vesting should start
* @param claimValidityDate Date before which the claimable schedule must be claimed
* @param cliffDate Timestamp of cliff exectution - if 0, startDate acts as cliff
* @param cliffDate Timestamp of cliff execution - if 0, startDate acts as cliff
* @param flowRate The flowRate for the stream
* @param cliffAmount The amount to be transferred at the cliff
* @param endDate The timestamp when the stream should stop.
Expand Down Expand Up @@ -98,7 +98,7 @@ interface IVestingSchedulerV2 {
* @param superToken SuperToken to be vested
* @param receiver Vesting receiver
* @param startDate Timestamp when the vesting should start
* @param cliffDate Timestamp of cliff exectution - if 0, startDate acts as cliff
* @param cliffDate Timestamp of cliff execution - if 0, startDate acts as cliff
* @param flowRate The flowRate for the stream
* @param cliffAmount The amount to be transferred at the cliff
* @param endDate The timestamp when the stream should stop.
Expand Down
2 changes: 1 addition & 1 deletion packages/js-sdk/src/utils/gasMetering/gasMetering.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ module.exports = class GasMeter {
// TODO
break;
default:
throw new Error(`Unsuported report type ${outputFormat}`);
throw new Error(`Unsupported report type ${outputFormat}`);
}
this.gasPrice = new this.BN(gasPrice);
this.records = [];
Expand Down
6 changes: 6 additions & 0 deletions packages/sdk-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Changed
### Fixed

## [0.9.0] - 2024-12-13

### Added
- Handle new Operation types with BatchCall
- Forward ETH value with BatchCall and Operation

## [0.8.0] - 2024-08-01

### Breaking
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk-core/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
{
"name": "@superfluid-finance/sdk-core",
"description": "SDK Core for building with Superfluid Protocol",
"version": "0.8.0",
"version": "0.9.0",
"bugs": "https://github.com/superfluid-finance/protocol-monorepo/issues",
"dependencies": {
"@superfluid-finance/ethereum-contracts": "1.12.0",
"@superfluid-finance/metadata": "^1.5.2",
"browserify": "17.0.0",
"graphql-request": "6.1.0",
"lodash": "4.17.21",
"tsify": "5.0.4"
Expand All @@ -16,6 +15,7 @@
"@graphql-codegen/near-operation-file-preset": "^3.0.0",
"@graphql-typed-document-node/core": "^3.2.0",
"ajv": "^8.17.1",
"browserify": "^17.0.1",
"ethers": "^5.7.2",
"get-graphql-schema": "^2.1.2",
"mocha": "^10.7.3"
Expand Down
28 changes: 23 additions & 5 deletions packages/sdk-core/src/BatchCall.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { JsonFragment } from "@ethersproject/abi";
import { ethers } from "ethers";
import { BigNumber, ethers } from "ethers";

import Host from "./Host";
import Operation, { BatchOperationType } from "./Operation";
Expand All @@ -15,6 +15,7 @@ export interface OperationStruct {
readonly operationType: number;
readonly target: string;
readonly data: string;
readonly value?: ethers.BigNumber;
}

export const batchOperationTypeStringToTypeMap = new Map<
Expand All @@ -30,6 +31,8 @@ export const batchOperationTypeStringToTypeMap = new Map<
["SUPERTOKEN_DOWNGRADE", 102],
["SUPERFLUID_CALL_AGREEMENT", 201],
["CALL_APP_ACTION", 202],
["SIMPLE_FORWARD_CALL", 301],
["ERC2771_FORWARD_CALL", 302],
]);

/**
Expand Down Expand Up @@ -89,10 +92,25 @@ export default class BatchCall {
const operationStructArray = await Promise.all(
this.getOperationStructArrayPromises
);
const tx =
this.host.contract.populateTransaction.batchCall(
operationStructArray
);

const values = operationStructArray
.filter((x) => x.value?.gt(BigNumber.from(0)))
.map((x) => x.value);

if (values.length > 1) {
throw new SFError({
type: "BATCH_CALL_ERROR",
message:
"There are multiple values in the batch call. The value can only be forwarded to one receiving operation.",
});
}

const tx = this.host.contract.populateTransaction.batchCall(
operationStructArray,
{
value: values?.length > 0 ? values[0] : undefined,
}
);
return new Operation(tx, "UNSUPPORTED");
}

Expand Down
21 changes: 19 additions & 2 deletions packages/sdk-core/src/Operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export type BatchOperationType =
| "SUPERTOKEN_UPGRADE" // 101
| "SUPERTOKEN_DOWNGRADE" // 102
| "SUPERFLUID_CALL_AGREEMENT" // 201
| "CALL_APP_ACTION"; // 202
| "CALL_APP_ACTION" // 202
| "SIMPLE_FORWARD_CALL" // 301
| "ERC2771_FORWARD_CALL"; // 302

/**
* Operation Helper Class
Expand Down Expand Up @@ -164,6 +166,7 @@ export default class Operation {
operationType: batchOperationType,
target: functionArgs["agreementClass"],
data,
value: populatedTransaction.value,
};
}

Expand All @@ -178,14 +181,28 @@ export default class Operation {
operationType: batchOperationType,
target: functionArgs["app"],
data: functionArgs["callData"],
value: populatedTransaction.value,
};
}

// Handles remaining ERC20/ERC777/SuperToken Operations
if (
this.type === "SIMPLE_FORWARD_CALL" ||
this.type === "ERC2771_FORWARD_CALL"
) {
return {
operationType: batchOperationType,
target: populatedTransaction.to,
data: populatedTransaction.data,
value: populatedTransaction.value,
};
}

// Handles remaining ERC20/ERC777/SuperToken Operations (including SIMPLE_FORWARD_CALL and ERC2771_FORWARD_CALL)
return {
operationType: batchOperationType,
target: populatedTransaction.to,
data: removeSigHashFromCallData(populatedTransaction.data),
value: populatedTransaction.value,
};
};
}
29 changes: 28 additions & 1 deletion packages/sdk-core/test/2_operation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { SuperAppTester } from "../typechain-types";
import { SuperAppTester__factory } from "../typechain-types";
const cfaInterface = IConstantFlowAgreementV1__factory.createInterface();
import { TestEnvironment, makeSuite } from "./TestEnvironment";
import { ethers } from "ethers";
import { BigNumber, ethers } from "ethers";
import multiplyGasLimit from "../src/multiplyGasLimit";

/**
Expand Down Expand Up @@ -174,6 +174,33 @@ makeSuite("Operation Tests", (testEnv: TestEnvironment) => {
expect(txn.gasLimit).to.equal("500000");
});

it("Should move ETH value passed from the Overrides", async () => {
const value = BigNumber.from(Number(0.1e18).toString());

const beforeBalanceAlice = await testEnv.alice.getBalance();
const beforeBalanceBob = await testEnv.bob.getBalance();

expect(beforeBalanceAlice.gt(value)).to.be.true;

const operation = testEnv.sdkFramework.operation(
testEnv.alice.populateTransaction({
to: testEnv.bob.address,
value
}) as Promise<ethers.PopulatedTransaction>,
"SIMPLE_FORWARD_CALL"
);

const txn = await operation.exec(testEnv.alice, 2);
const txReceipt = await txn.wait();
expect(txReceipt.status).to.equal(1);

const afterBalanceAlice = await testEnv.alice.getBalance();
const afterBalanceBob = await testEnv.bob.getBalance();

expect(afterBalanceBob.sub(beforeBalanceBob)).to.equal(value);
expect(beforeBalanceAlice.sub(afterBalanceAlice).gte(value)).to.be.true;
});

it("Should throw an error when trying to execute a transaction with faulty callData", async () => {
const callData = cfaInterface.encodeFunctionData("createFlow", [
testEnv.wrapperSuperToken.address,
Expand Down
115 changes: 114 additions & 1 deletion packages/sdk-core/test/3_batch_call.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { expect } from "chai";
import {
AUTHORIZE_FULL_CONTROL,
Operation,
TestToken,
TestToken__factory,
getPerSecondFlowRateByMonth,
toBN,
} from "../src";
import { ethers } from "ethers";
import { BigNumber, Contract, ethers } from "ethers";
import { createCallAppActionOperation } from "./2_operation.test";
import { TestEnvironment, makeSuite } from "./TestEnvironment";

Expand Down Expand Up @@ -408,4 +410,115 @@ makeSuite("Batch Call Tests", (testEnv: TestEnvironment) => {
"0"
);
});


it("Should be able to execute SimpleForwarder batch call", async () => {
const contract = (new Contract(
testEnv.wrapperSuperToken.underlyingToken.address,
TestToken__factory.abi
) as TestToken).connect(testEnv.alice);

const beforeBalance = await contract.balanceOf(testEnv.alice.address);

const txn1 = contract
.populateTransaction.mint(
testEnv.alice.address,
"100"
);
const txn2 = contract
.populateTransaction.mint(
testEnv.alice.address,
"200"
);

const operation1 = testEnv.sdkFramework.operation(
txn1,
"SIMPLE_FORWARD_CALL"
);
const operation2 = testEnv.sdkFramework.operation(
txn2,
"SIMPLE_FORWARD_CALL"
);

const batchCall = testEnv.sdkFramework.batchCall(
[
operation1,
operation2
]
);

const txResponse = await batchCall.exec(testEnv.alice);
const txReceipt = await txResponse.wait();
expect(txReceipt.status).to.equal(1);

const afterBalance = await contract.balanceOf(testEnv.alice.address);

expect(beforeBalance.lt(afterBalance)).to.be.true;
expect(afterBalance.sub(BigNumber.from(300)).eq(beforeBalance)).to.be.true;
});

it("Should be able to move ETH value", async () => {
const value = BigNumber.from(Number(0.1e18).toString());

const beforeBalanceAlice = await testEnv.alice.getBalance();
const beforeBalanceBob = await testEnv.bob.getBalance();

expect(beforeBalanceAlice.gt(value)).to.be.true;

const operation = testEnv.sdkFramework.operation(
testEnv.alice.populateTransaction({
to: testEnv.bob.address,
value,
data: "0x"
}) as Promise<ethers.PopulatedTransaction>,
"SIMPLE_FORWARD_CALL"
);

const batchCall = testEnv.sdkFramework.batchCall(
[
operation
]
);

const txn = await batchCall.exec(testEnv.alice, 2);

const txReceipt = await txn.wait();
expect(txReceipt.status).to.equal(1);

const afterBalanceAlice = await testEnv.alice.getBalance();
const afterBalanceBob = await testEnv.bob.getBalance();

expect(afterBalanceBob.sub(beforeBalanceBob)).to.equal(value);
expect(beforeBalanceAlice.sub(afterBalanceAlice).gte(value)).to.be.true;
});

it("Should throw an error when multiple Operations with ETH value", async () => {
const operation1 = testEnv.sdkFramework.operation(
testEnv.alice.populateTransaction({
to: testEnv.bob.address,
value: BigNumber.from(Number(0.1e18).toString()),
data: "0x"
}) as Promise<ethers.PopulatedTransaction>,
"SIMPLE_FORWARD_CALL"
);

const operation2 = testEnv.sdkFramework.operation(
testEnv.alice.populateTransaction({
to: testEnv.bob.address,
value: BigNumber.from(Number(0.2e18).toString()),
data: "0x"
}) as Promise<ethers.PopulatedTransaction>,
"SIMPLE_FORWARD_CALL"
);

const batchCall = testEnv.sdkFramework.batchCall(
[
operation1,
operation2
]
);

await expect(batchCall.exec(testEnv.alice, 2))
.to.be.rejectedWith("multiple values in the batch call");
});
});
2 changes: 1 addition & 1 deletion packages/subgraph/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"dependencies": {
"@graphprotocol/graph-cli": "0.80.1",
"@graphprotocol/graph-ts": "0.35.1",
"@superfluid-finance/sdk-core": "0.8.0",
"@superfluid-finance/sdk-core": "0.9.0",
"mustache": "4.2.0"
},
"devDependencies": {
Expand Down
Loading
Loading