|
@@ -2,13 +2,14 @@ const { ethers } = require('hardhat');
|
|
const { expect } = require('chai');
|
|
const { expect } = require('chai');
|
|
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
|
|
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
|
|
const {
|
|
const {
|
|
|
|
+ CALL_TYPE_CALL,
|
|
|
|
+ CALL_TYPE_BATCH,
|
|
|
|
+ CALL_TYPE_DELEGATE,
|
|
EXEC_TYPE_DEFAULT,
|
|
EXEC_TYPE_DEFAULT,
|
|
EXEC_TYPE_TRY,
|
|
EXEC_TYPE_TRY,
|
|
encodeSingle,
|
|
encodeSingle,
|
|
encodeBatch,
|
|
encodeBatch,
|
|
encodeDelegate,
|
|
encodeDelegate,
|
|
- CALL_TYPE_CALL,
|
|
|
|
- CALL_TYPE_BATCH,
|
|
|
|
encodeMode,
|
|
encodeMode,
|
|
} = require('../../helpers/erc7579');
|
|
} = require('../../helpers/erc7579');
|
|
const { selector } = require('../../helpers/methods');
|
|
const { selector } = require('../../helpers/methods');
|
|
@@ -29,6 +30,14 @@ describe('ERC7579Utils', function () {
|
|
Object.assign(this, await loadFixture(fixture));
|
|
Object.assign(this, await loadFixture(fixture));
|
|
});
|
|
});
|
|
|
|
|
|
|
|
+ it('constants', async function () {
|
|
|
|
+ await expect(this.utils.$CALLTYPE_SINGLE()).to.eventually.equal(CALL_TYPE_CALL);
|
|
|
|
+ await expect(this.utils.$CALLTYPE_BATCH()).to.eventually.equal(CALL_TYPE_BATCH);
|
|
|
|
+ await expect(this.utils.$CALLTYPE_DELEGATECALL()).to.eventually.equal(CALL_TYPE_DELEGATE);
|
|
|
|
+ await expect(this.utils.$EXECTYPE_DEFAULT()).to.eventually.equal(EXEC_TYPE_DEFAULT);
|
|
|
|
+ await expect(this.utils.$EXECTYPE_TRY()).to.eventually.equal(EXEC_TYPE_TRY);
|
|
|
|
+ });
|
|
|
|
+
|
|
describe('execSingle', function () {
|
|
describe('execSingle', function () {
|
|
it('calls the target with value', async function () {
|
|
it('calls the target with value', async function () {
|
|
const value = 0x012;
|
|
const value = 0x012;
|
|
@@ -54,6 +63,18 @@ describe('ERC7579Utils', function () {
|
|
await expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value);
|
|
await expect(ethers.provider.getBalance(this.target)).to.eventually.equal(value);
|
|
});
|
|
});
|
|
|
|
|
|
|
|
+ it('default to calling self is target is address(0) (ERC-7821 calldata compression)', async function () {
|
|
|
|
+ const data = encodeSingle(
|
|
|
|
+ ethers.ZeroAddress, // address(0)
|
|
|
|
+ 0,
|
|
|
|
+ this.utils.interface.encodeFunctionData('$CALLTYPE_SINGLE', []),
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ await expect(this.utils.$execSingle(data, EXEC_TYPE_DEFAULT))
|
|
|
|
+ .to.emit(this.utils, 'return$execSingle')
|
|
|
|
+ .withArgs([ethers.zeroPadBytes(CALL_TYPE_CALL, 32)]);
|
|
|
|
+ });
|
|
|
|
+
|
|
it('reverts when target reverts in default ExecType', async function () {
|
|
it('reverts when target reverts in default ExecType', async function () {
|
|
const value = 0x012;
|
|
const value = 0x012;
|
|
const data = encodeSingle(
|
|
const data = encodeSingle(
|
|
@@ -131,6 +152,17 @@ describe('ERC7579Utils', function () {
|
|
await expect(ethers.provider.getBalance(this.anotherTarget)).to.eventually.equal(value2);
|
|
await expect(ethers.provider.getBalance(this.anotherTarget)).to.eventually.equal(value2);
|
|
});
|
|
});
|
|
|
|
|
|
|
|
+ it('default to calling self is target is address(0) (ERC-7821 calldata compression)', async function () {
|
|
|
|
+ const data = encodeBatch(
|
|
|
|
+ [ethers.ZeroAddress, 0, this.utils.interface.encodeFunctionData('$CALLTYPE_SINGLE', [])],
|
|
|
|
+ [ethers.ZeroAddress, 0, this.utils.interface.encodeFunctionData('$CALLTYPE_BATCH', [])],
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ await expect(this.utils.$execBatch(data, EXEC_TYPE_DEFAULT))
|
|
|
|
+ .to.emit(this.utils, 'return$execBatch')
|
|
|
|
+ .withArgs([ethers.zeroPadBytes(CALL_TYPE_CALL, 32), ethers.zeroPadBytes(CALL_TYPE_BATCH, 32)]);
|
|
|
|
+ });
|
|
|
|
+
|
|
it('reverts when any target reverts in default ExecType', async function () {
|
|
it('reverts when any target reverts in default ExecType', async function () {
|
|
const value1 = 0x012;
|
|
const value1 = 0x012;
|
|
const value2 = 0x234;
|
|
const value2 = 0x234;
|
|
@@ -193,6 +225,17 @@ describe('ERC7579Utils', function () {
|
|
await expect(ethers.provider.getStorage(this.utils.target, slot)).to.eventually.equal(value);
|
|
await expect(ethers.provider.getStorage(this.utils.target, slot)).to.eventually.equal(value);
|
|
});
|
|
});
|
|
|
|
|
|
|
|
+ it('default to calling self is target is address(0) (ERC-7821 calldata compression)', async function () {
|
|
|
|
+ const data = encodeDelegate(
|
|
|
|
+ ethers.ZeroAddress,
|
|
|
|
+ this.utils.interface.encodeFunctionData('$CALLTYPE_DELEGATECALL', []),
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ await expect(this.utils.$execDelegateCall(data, EXEC_TYPE_DEFAULT))
|
|
|
|
+ .to.emit(this.utils, 'return$execDelegateCall')
|
|
|
|
+ .withArgs([ethers.zeroPadBytes(CALL_TYPE_DELEGATE, 32)]);
|
|
|
|
+ });
|
|
|
|
+
|
|
it('reverts when target reverts in default ExecType', async function () {
|
|
it('reverts when target reverts in default ExecType', async function () {
|
|
const data = encodeDelegate(this.target, this.target.interface.encodeFunctionData('mockFunctionRevertsReason'));
|
|
const data = encodeDelegate(this.target, this.target.interface.encodeFunctionData('mockFunctionRevertsReason'));
|
|
await expect(this.utils.$execDelegateCall(data, EXEC_TYPE_DEFAULT)).to.be.revertedWith(
|
|
await expect(this.utils.$execDelegateCall(data, EXEC_TYPE_DEFAULT)).to.be.revertedWith(
|