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

Fix testcase #113

Merged
merged 4 commits into from
Dec 18, 2023
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
60 changes: 30 additions & 30 deletions script/op_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,73 +33,73 @@ const OP_FULLEXIT_HASH_SIZE = 43;
const ADDRESS_PREFIX_ZERO_BYTES = "0x000000000000000000000000";

function getDepositPubdata({ chainId, accountId, subAccountId, tokenId, targetTokenId, amount, owner }) {
const pubdata = ethers.utils.solidityPack(["uint8","uint8","uint8","uint16","uint16","uint128","bytes32","uint32"],
const pubdata = ethers.solidityPacked(["uint8","uint8","uint8","uint16","uint16","uint128","bytes32","uint32"],
[OP_DEPOSIT,chainId,subAccountId,tokenId,targetTokenId,amount,owner,accountId]);
const pubdataArray = ethers.utils.arrayify(pubdata);
const pubdataArray = arrayify(pubdata);
console.assert(pubdataArray.length === OP_DEPOSIT_SIZE, "wrong deposit pubdata");
return pubdata;
}

function writeDepositPubdata({ chainId, subAccountId, tokenId, targetTokenId, amount, owner }) {
return ethers.utils.solidityPack(["uint8","uint8","uint8","uint16","uint16","uint128","bytes32","uint32"],
return ethers.solidityPacked(["uint8","uint8","uint8","uint16","uint16","uint128","bytes32","uint32"],
[OP_DEPOSIT,chainId,subAccountId,tokenId,targetTokenId,amount,owner,0]);
}

function getWithdrawPubdata({ chainId, accountId, subAccountId, tokenId, srcTokenId, amount, fee, owner, nonce, fastWithdrawFeeRate, withdrawToL1 }) {
const pubdata = ethers.utils.solidityPack(["uint8","uint8","uint32","uint8","uint16","uint16","uint128","uint16","bytes32","uint32","uint16","uint8"],
const pubdata = ethers.solidityPacked(["uint8","uint8","uint32","uint8","uint16","uint16","uint128","uint16","bytes32","uint32","uint16","uint8"],
[OP_WITHDRAW,chainId,accountId,subAccountId,tokenId,srcTokenId,amount,fee,owner,nonce,fastWithdrawFeeRate,withdrawToL1]);
const pubdataArray = ethers.utils.arrayify(pubdata);
const pubdataArray = arrayify(pubdata);
console.assert(pubdataArray.length === OP_WITHDRAW_SIZE, "wrong withdraw pubdata");
return pubdata;
}

function getFullExitPubdata({ chainId, accountId, subAccountId, owner, tokenId, srcTokenId, amount}) {
const pubdata = ethers.utils.solidityPack(["uint8","uint8","uint32","uint8","bytes32","uint16","uint16","uint128"],
const pubdata = ethers.solidityPacked(["uint8","uint8","uint32","uint8","bytes32","uint16","uint16","uint128"],
[OP_FULL_EXIT,chainId,accountId,subAccountId,owner,tokenId,srcTokenId,amount]);
const pubdataArray = ethers.utils.arrayify(pubdata);
const pubdataArray = arrayify(pubdata);
console.assert(pubdataArray.length === OP_FULL_EXIT_SIZE, "wrong fullexit pubdata");
return pubdata;
}

function writeFullExitPubdata({ chainId, accountId, subAccountId, owner, tokenId, srcTokenId}) {
return ethers.utils.solidityPack(["uint8","uint8","uint32","uint8","bytes32","uint16","uint16","uint128"],
return ethers.solidityPacked(["uint8","uint8","uint32","uint8","bytes32","uint16","uint16","uint128"],
[OP_FULL_EXIT,chainId,accountId,subAccountId,owner,tokenId,srcTokenId,0]);
}

function getForcedExitPubdata({ chainId, initiatorAccountId, initiatorSubAccountId, initiatorNonce, targetAccountId, targetSubAccountId, tokenId, srcTokenId, amount, withdrawToL1, target }) {
const pubdata = ethers.utils.solidityPack(["uint8","uint8","uint32","uint8","uint32","uint32","uint8","uint16","uint16","uint128","uint8","bytes32"],
const pubdata = ethers.solidityPacked(["uint8","uint8","uint32","uint8","uint32","uint32","uint8","uint16","uint16","uint128","uint8","bytes32"],
[OP_FORCE_EXIT,chainId,initiatorAccountId,initiatorSubAccountId,initiatorNonce,targetAccountId,targetSubAccountId,tokenId,srcTokenId,amount,withdrawToL1,target]);
const pubdataArray = ethers.utils.arrayify(pubdata);
const pubdataArray = arrayify(pubdata);
console.assert(pubdataArray.length === OP_FORCE_EXIT_SIZE, "wrong forcedexit pubdata");
return pubdata;
}

function getChangePubkeyPubdata({ chainId, accountId, subAccountId, pubKeyHash, owner, nonce, tokenId, fee}) {
const pubdata = ethers.utils.solidityPack(["uint8","uint8","uint32","uint8","bytes20","bytes32","uint32","uint16","uint16"],
const pubdata = ethers.solidityPacked(["uint8","uint8","uint32","uint8","bytes20","bytes32","uint32","uint16","uint16"],
[OP_CHANGE_PUBKEY,chainId,accountId,subAccountId,pubKeyHash,owner,nonce,tokenId,fee]);
const pubdataArray = ethers.utils.arrayify(pubdata);
const pubdataArray = arrayify(pubdata);
console.assert(pubdataArray.length === OP_CHANGE_PUBKEY_SIZE, "wrong changepubkey pubdata");
return pubdata;
}

function getTransferPubdata({fromAccountId, fromSubAccountId, tokenId, amount, toAccountId, toSubAccountId, fee}) {
const pubdata = ethers.utils.solidityPack(["uint8","uint32","uint8","uint16","uint40","uint32","uint8","uint16"],
const pubdata = ethers.solidityPacked(["uint8","uint32","uint8","uint16","uint40","uint32","uint8","uint16"],
[OP_TRANSFER,fromAccountId,fromSubAccountId,tokenId,amount,toAccountId,toSubAccountId,fee]);
const pubdataArray = ethers.utils.arrayify(pubdata);
const pubdataArray = arrayify(pubdata);
console.assert(pubdataArray.length === OP_TRANSFER_SIZE, "wrong transfer pubdata");
return pubdata;
}

function getTransferToNewPubdata({fromAccountId, fromSubAccountId, tokenId, amount, toAccountId, toSubAccountId, to, fee}) {
const pubdata = ethers.utils.solidityPack(["uint8","uint32","uint8","uint16","uint40","bytes32","uint32","uint8","uint16"],
const pubdata = ethers.solidityPacked(["uint8","uint32","uint8","uint16","uint40","bytes32","uint32","uint8","uint16"],
[OP_TRANSFER_TO_NEW,fromAccountId,fromSubAccountId,tokenId,amount,to,toAccountId,toSubAccountId,fee]);
const pubdataArray = ethers.utils.arrayify(pubdata);
const pubdataArray = arrayify(pubdata);
console.assert(pubdataArray.length === OP_TRANSFER_TO_NEW_SIZE, "wrong transfertonew pubdata");
return pubdata;
}

function getOrderMatchingPubdata({submitterAccountId, taker, maker, feeTokenId, fee, baseAmount, quoteAmount}) {
const pubdata = ethers.utils.solidityPack(["uint8",
const pubdata = ethers.solidityPacked(["uint8",
"uint8",
"uint32","uint32","uint32",
"uint16","uint16",
Expand All @@ -123,21 +123,21 @@ function getOrderMatchingPubdata({submitterAccountId, taker, maker, feeTokenId,
maker.nonce,taker.nonce,
maker.is_sell
]);
const pubdataArray = ethers.utils.arrayify(pubdata);
const pubdataArray = arrayify(pubdata);
console.assert(pubdataArray.length === OP_ORDER_MATCHING_SIZE, "wrong ordermatching pubdata");
return pubdata;
}

function mockNoopPubdata() {
return ethers.utils.solidityPack(["uint8"], [OP_NOOP]);
return ethers.solidityPacked(["uint8"], [OP_NOOP]);
}

function paddingChunk(pubdata, chunks) {
const pubdataArray = ethers.utils.arrayify(pubdata);
const pubdataArray = arrayify(pubdata);
const zeroPaddingNum = CHUNK_BYTES * chunks - pubdataArray.length;
const zeroArray = new Uint8Array(zeroPaddingNum);
const pubdataPaddingArray = ethers.utils.concat([pubdataArray, zeroArray]);
return ethers.utils.hexlify(pubdataPaddingArray);
const pubdataPaddingArray = concat([pubdataArray, zeroArray]);
return hexlify(pubdataPaddingArray);
}

function extendAddress(address) {
Expand All @@ -148,26 +148,26 @@ function extendAddress(address) {
}

function hashBytesToBytes20(pubData) {
return ethers.utils.hexlify(ethers.utils.arrayify(ethers.utils.keccak256(pubData)).slice(12));
return hexlify(arrayify(ethers.keccak256(pubData)).slice(12));
}

async function createEthWitnessOfECRECOVER(pubKeyHash,nonce,accountId,owner) {
const sigMsg = ethers.utils.solidityPack(
const sigMsg = ethers.solidityPacked(
["string"],
["ChangePubKey\nPubKeyHash: " + pubKeyHash + "\nNonce: " + nonce + "\nAccountId: " + accountId]);
const signature = await owner.signMessage(ethers.utils.arrayify(sigMsg));
return ethers.utils.solidityPack(["bytes1","bytes"],[0, signature]);
const signature = await owner.signMessage(arrayify(sigMsg));
return ethers.solidityPacked(["bytes1","bytes"],['0x00', signature]);
}

function createEthWitnessOfCREATE2(pubKeyHash,accountId,creatorAddress,saltArg,codeHash) {
const ethWitness = ethers.utils.solidityPack(["bytes1","address","bytes32","bytes32"],[1, creatorAddress, saltArg, codeHash]);
const salt = ethers.utils.keccak256(ethers.utils.arrayify(ethers.utils.solidityPack(["bytes32","bytes20"],[saltArg, pubKeyHash])));
const owner = ethers.utils.getCreate2Address(creatorAddress, ethers.utils.arrayify(salt), ethers.utils.arrayify(codeHash));
const ethWitness = ethers.solidityPacked(["bytes1","address","bytes32","bytes32"],["0x01", creatorAddress, saltArg, codeHash]);
const salt = ethers.keccak256(arrayify(ethers.solidityPacked(["bytes32","bytes20"],[saltArg, pubKeyHash])));
const owner = ethers.getCreate2Address(creatorAddress, arrayify(salt), arrayify(codeHash));
return {ethWitness, owner};
}

function calWithdrawHash(receiver, token, amount, fastWithdrawFeeRate, accountIdOfNonce, subAccountIdOfNonce, nonce) {
return ethers.utils.keccak256(ethers.utils.solidityPack(["uint32","uint8","uint32", "address","address","uint128","uint16"], [accountIdOfNonce, subAccountIdOfNonce, nonce, receiver, token, amount, fastWithdrawFeeRate]));
return ethers.keccak256(ethers.solidityPacked(["uint32","uint8","uint32", "address","address","uint128","uint16"], [accountIdOfNonce, subAccountIdOfNonce, nonce, receiver, token, amount, fastWithdrawFeeRate]));
}

function getRandomInt(max) {
Expand Down
21 changes: 10 additions & 11 deletions test/accept_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ const { ethers } = require('hardhat');
const { expect } = require('chai');
const { deploy, MAX_ACCEPT_FEE_RATE, ETH_ADDRESS } = require('./utils');
const { calWithdrawHash } = require('../script/op_utils');
const {parseEther} = require("ethers/lib/utils");

const { parseEther } = require("ethers")
describe('Accept unit tests', function () {
let deployedInfo;
let zkLink, periphery, ethId, token2, token2Id, defaultSender, alice, bob;
Expand All @@ -21,7 +20,7 @@ describe('Accept unit tests', function () {

it('invalid state or params should failed when accept', async () => {
// receiver is zero address
await expect(periphery.connect(alice).acceptETH(ethers.constants.AddressZero, 100, 20, 10, 0, 1))
await expect(periphery.connect(alice).acceptETH(ethers.ZeroAddress, 100, 20, 10, 0, 1))
.to.be.revertedWith("H1");
// acceptor = receiver
await expect(periphery.connect(alice).acceptETH(alice.address, 100, 20, 10, 0, 1))
Expand Down Expand Up @@ -62,11 +61,11 @@ describe('Accept unit tests', function () {
.to.be.emit(periphery, "Accept")
.withArgs(alice.address, bob.address, ETH_ADDRESS, amount, feeRate, accountIdOfNonce, subAccountIdOfNonce, nonce, amountReceive);
// periphery should have no eth
expect(await ethers.provider.getBalance(periphery.address)).to.be.eq(0);
expect(await ethers.provider.getBalance(periphery.target)).to.be.eq(0);

// send eth to a contract that has no receive or fallback function
nonce = 3;
await expect(periphery.connect(alice).acceptETH(token2.address, amount, feeRate, accountIdOfNonce, subAccountIdOfNonce, nonce, {value: amountReceive}))
await expect(periphery.connect(alice).acceptETH(token2.target, amount, feeRate, accountIdOfNonce, subAccountIdOfNonce, nonce, {value: amountReceive}))
.to.be.reverted;
});

Expand All @@ -78,18 +77,18 @@ describe('Accept unit tests', function () {
let nonce = 1;
const amountReceive = parseEther("0.99");
await token2.connect(bob).mint(parseEther("100"));
await token2.connect(bob).approve(periphery.address, amount);
await expect(periphery.connect(bob).acceptERC20(alice.address, token2.address, amount, feeRate, accountIdOfNonce, subAccountIdOfNonce, nonce))
await token2.connect(bob).approve(periphery.target, amount);
await expect(periphery.connect(bob).acceptERC20(alice.address, token2.target, amount, feeRate, accountIdOfNonce, subAccountIdOfNonce, nonce))
.to.be.emit(periphery, "Accept")
.withArgs(bob.address, alice.address, token2.address, amount, feeRate, accountIdOfNonce, subAccountIdOfNonce, nonce, amountReceive);
let hash = calWithdrawHash(alice.address, token2.address, amount, feeRate, accountIdOfNonce, subAccountIdOfNonce, nonce);
.withArgs(bob.address, alice.address, token2.target, amount, feeRate, accountIdOfNonce, subAccountIdOfNonce, nonce, amountReceive);
let hash = calWithdrawHash(alice.address, token2.target, amount, feeRate, accountIdOfNonce, subAccountIdOfNonce, nonce);
expect(await periphery.accepts(hash)).to.be.eq(bob.address);
expect(await token2.balanceOf(alice.address)).to.be.eq(amountReceive);

// approve value not enough
await token2.connect(bob).approve(periphery.address, parseEther("0.98"));
await token2.connect(bob).approve(periphery.target, parseEther("0.98"));
nonce = 2;
await expect(periphery.connect(bob).acceptERC20(alice.address, token2.address, amount, feeRate, accountIdOfNonce, subAccountIdOfNonce, nonce))
await expect(periphery.connect(bob).acceptERC20(alice.address, token2.target, amount, feeRate, accountIdOfNonce, subAccountIdOfNonce, nonce))
.to.be.revertedWith("ERC20: insufficient allowance");
});
});
15 changes: 8 additions & 7 deletions test/block_commit_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ const {
OP_FORCE_EXIT_CHUNKS,
extendAddress
} = require('../script/op_utils');
const { keccak256, arrayify, hexlify, concat, parseEther} = require("ethers/lib/utils");
const { parseEther,keccak256} = require("ethers");
const { arrayify, hexlify, concat } = require("@ethersproject/bytes")

if (!IS_MASTER_CHAIN) {
console.log("Block commit unit tests only support master chain");
Expand Down Expand Up @@ -369,15 +370,15 @@ describe('Block commit unit tests', function () {

it('invalid block timestamp should be failed', async () => {
commitBlock.blockNumber = 11;
const l1Block = await zkLink.provider.getBlock('latest');
const l1Block = await zkLink.runner.provider.getBlock('latest');
preBlock.timestamp = l1Block.timestamp;
commitBlock.timestamp = preBlock.timestamp - 1;
await expect(zkLink.testCommitOneBlock(preBlock, commitBlock))
.to.be.revertedWith("g2");
});

it('commit block should success', async () => {
const l1Block = await zkLink.provider.getBlock('latest');
const l1Block = await zkLink.runner.provider.getBlock('latest');
preBlock.timestamp = l1Block.timestamp;
commitBlock.timestamp = preBlock.timestamp + 1;

Expand All @@ -389,15 +390,15 @@ describe('Block commit unit tests', function () {
commitBlock.onchainOperations = fullBlock.onchainOperations;

const r = await zkLink.testCommitOneBlock(preBlock, commitBlock);
expect(r.blockNumber).to.eql(commitBlock.blockNumber);
expect(r.priorityOperations).to.eql(BigNumber.from(expected.priorityOperationsProcessed));
expect(Number(r.blockNumber)).to.eql(commitBlock.blockNumber);
expect(Number(r.priorityOperations)).to.eql(expected.priorityOperationsProcessed);
expect(r.pendingOnchainOperationsHash).to.eql(expected.processableOpPubdataHash);
expect(r.timestamp).to.eql(BigNumber.from(commitBlock.timestamp));
expect(Number(r.timestamp)).to.eql(commitBlock.timestamp);
expect(r.stateHash).to.eql(commitBlock.newStateHash);

const syncHash2 = hexlify(createSlaverChainSyncHash(EMPTY_STRING_KECCAK, commitBlock.blockNumber, commitBlock.newStateHash, expected.onchainOperationPubdataHashs[1]));
const syncHash4 = hexlify(createSlaverChainSyncHash(EMPTY_STRING_KECCAK, commitBlock.blockNumber, commitBlock.newStateHash, expected.onchainOperationPubdataHashs[3]));
expect(r.syncHashs).to.eql([[2, syncHash2],[4, syncHash4]]);
expect(r.syncHashs).to.eql([[2n, syncHash2],[4n, syncHash4]]);
});
});
});
2 changes: 1 addition & 1 deletion test/bytes_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('Bytes unit tests', function () {
it('should read bytes', async () => {
let r = await testContract.read('0x0102030405060708', 4, 2);
expect(r.data).equal('0x0506');
expect(r.new_offset).equal(BigNumber.from(6));
expect(r.new_offset).equal(6);
});

it('should fail to read bytes beyond range', async () => {
Expand Down
10 changes: 5 additions & 5 deletions test/change_pubkey_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('ZkLink change pubkey unit tests', function () {
const pubkeyHash = '0xfefefefefefefefefefefefefefefefefefefefe';
await periphery.connect(alice).setAuthPubkeyHash(pubkeyHash, nonce);

const expectedAuthFact = ethers.utils.keccak256(pubkeyHash);
const expectedAuthFact = ethers.keccak256(pubkeyHash);
expect(await periphery.getAuthFact(alice.address, nonce)).to.eq(expectedAuthFact);
});

Expand All @@ -35,15 +35,15 @@ describe('ZkLink change pubkey unit tests', function () {
expect(await periphery.getAuthFact(alice.address, nonce)).to.eq(oldHash);

// must wait 24 hours
const latestBlock = await zkLink.provider.getBlock('latest');
const latestBlock = await zkLink.runner.provider.getBlock('latest');
const resetTimestampTooEarly = latestBlock.timestamp + 23 * 60 * 60;
await zkLink.provider.send('evm_setNextBlockTimestamp', [resetTimestampTooEarly]);
await zkLink.runner.provider.send('evm_setNextBlockTimestamp', [resetTimestampTooEarly]);
await expect(periphery.connect(alice).setAuthPubkeyHash(newPubkeyHash, nonce)).to.be.revertedWith("B1");

const resetTimestamp = latestBlock.timestamp + 24 * 60 * 60;
await zkLink.provider.send('evm_setNextBlockTimestamp', [resetTimestamp]);
await zkLink.runner.provider.send('evm_setNextBlockTimestamp', [resetTimestamp]);
await periphery.connect(alice).setAuthPubkeyHash(newPubkeyHash, nonce);
expect(await periphery.getAuthFact(alice.address, nonce)).to.eq(ethers.utils.keccak256(newPubkeyHash));
expect(await periphery.getAuthFact(alice.address, nonce)).to.eq(ethers.keccak256(newPubkeyHash));
});

it('verify CREATE2 should be success', async () => {
Expand Down
9 changes: 5 additions & 4 deletions test/compressed_block_commit_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ const {
OP_FORCE_EXIT_CHUNKS,
extendAddress
} = require('../script/op_utils');
const { keccak256, arrayify, hexlify, concat, parseEther} = require("ethers/lib/utils");
const { keccak256, parseEther} = require("ethers");
const { arrayify, hexlify, concat } = require("@ethersproject/bytes")

if (IS_MASTER_CHAIN) {
console.log("Compressed block commit unit tests only support slaver chain");
Expand Down Expand Up @@ -150,15 +151,15 @@ describe('Compressed block commit unit tests', function () {
const block = testBlockInfo.block;
const expected = testBlockInfo.expected;

commitBlock.blockNumber = 13;
commitBlock.blockNumber = 13n
commitBlock.publicData = block.publicData;
commitBlock.onchainOperations = block.onchainOperations;

const r = await zkLink.testCommitOneBlock(preBlock, commitBlock);
const syncHash = hexlify(createSlaverChainSyncHash(preBlock.syncHash, commitBlock.blockNumber, commitBlock.newStateHash, expected.onchainOperationPubdataHash));
expect(r.blockNumber).to.eql(commitBlock.blockNumber);
expect(r.blockSequence).to.eql(preBlock.blockSequence + 1);
expect(r.priorityOperations).to.eql(BigNumber.from(expected.priorityOperationsProcessed));
expect(r.blockSequence).to.eql(BigInt(preBlock.blockSequence + 1));
expect(r.priorityOperations).to.eql(BigInt(expected.priorityOperationsProcessed));
expect(r.pendingOnchainOperationsHash).to.eql(expected.processableOpPubdataHash);
expect(r.syncHash).to.eql(syncHash);
});
Expand Down
Loading