From 5a3193442cbb2665d374a43ffca98e7d9be4aad7 Mon Sep 17 00:00:00 2001 From: CedarMist <134699267+CedarMist@users.noreply.github.com> Date: Thu, 28 Sep 2023 16:06:18 +0100 Subject: [PATCH 1/6] contracts: eth_call maximum return length vs gas limit --- contracts/contracts/tests/SemanticTests.sol | 10 ++++++++++ contracts/test/semantics.ts | 22 +++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 contracts/contracts/tests/SemanticTests.sol create mode 100644 contracts/test/semantics.ts diff --git a/contracts/contracts/tests/SemanticTests.sol b/contracts/contracts/tests/SemanticTests.sol new file mode 100644 index 00000000..6ae15a3f --- /dev/null +++ b/contracts/contracts/tests/SemanticTests.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +contract SemanticTests { + function testViewLength (uint256 len) external pure returns (bytes memory) + { + return new bytes(len); + } +} \ No newline at end of file diff --git a/contracts/test/semantics.ts b/contracts/test/semantics.ts new file mode 100644 index 00000000..7e1ee846 --- /dev/null +++ b/contracts/test/semantics.ts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 + +import { ethers } from 'hardhat'; +import { expect } from 'chai'; +import { SemanticTests } from '../typechain-types/contracts/tests/SemanticTests'; +import { SemanticTests__factory } from '../typechain-types/factories/contracts/tests'; + +describe('EVM Semantics', () => { + let c: SemanticTests; + before(async () => { + const f = await ethers.getContractFactory('SemanticTests') as SemanticTests__factory; + c = await f.deploy(); + await c.deployed(); + }); + it('eth_call maximum return length vs gas limit', async () => { + const i = 1787872; + const respHex = await c.testViewLength(i); + const respBytes = ethers.utils.arrayify(respHex); + expect(respBytes.length).eq(i); + expect(c.testViewLength(i+1)).reverted; + }) +}); \ No newline at end of file From 5778a8b64cdb92696e25b4d96f0ff58bc7dcb9eb Mon Sep 17 00:00:00 2001 From: CedarMist <134699267+CedarMist@users.noreply.github.com> Date: Thu, 28 Sep 2023 20:15:24 +0100 Subject: [PATCH 2/6] contracts: added tests for custom errors --- contracts/contracts/tests/SemanticTests.sol | 14 ++++++++ contracts/test/semantics.ts | 37 +++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/contracts/contracts/tests/SemanticTests.sol b/contracts/contracts/tests/SemanticTests.sol index 6ae15a3f..6948b036 100644 --- a/contracts/contracts/tests/SemanticTests.sol +++ b/contracts/contracts/tests/SemanticTests.sol @@ -7,4 +7,18 @@ contract SemanticTests { { return new bytes(len); } + + error CustomError(uint value); + uint private x; + + uint constant ERROR_NUM = 0x1023456789abcdef1023456789abcdef1023456789abcdef1023456789abcdef; + + function testCustomRevert () external { + x += 1; + revert CustomError(ERROR_NUM); + } + + function testCustomViewRevert () external pure returns (uint) { + revert CustomError(ERROR_NUM); + } } \ No newline at end of file diff --git a/contracts/test/semantics.ts b/contracts/test/semantics.ts index 7e1ee846..c23bb5ed 100644 --- a/contracts/test/semantics.ts +++ b/contracts/test/semantics.ts @@ -5,6 +5,8 @@ import { expect } from 'chai'; import { SemanticTests } from '../typechain-types/contracts/tests/SemanticTests'; import { SemanticTests__factory } from '../typechain-types/factories/contracts/tests'; +const ERROR_NUM = '0x1023456789abcdef1023456789abcdef1023456789abcdef1023456789abcdef'; + describe('EVM Semantics', () => { let c: SemanticTests; before(async () => { @@ -12,11 +14,42 @@ describe('EVM Semantics', () => { c = await f.deploy(); await c.deployed(); }); + it('eth_call maximum return length vs gas limit', async () => { const i = 1787872; const respHex = await c.testViewLength(i); const respBytes = ethers.utils.arrayify(respHex); expect(respBytes.length).eq(i); expect(c.testViewLength(i+1)).reverted; - }) -}); \ No newline at end of file + }); + + // Apparently `expect().to.be.revertedWithCustomError` doesn't work sometimes + // Otherwise we could do this: + //expect(c.testCustomRevert()).to.be.revertedWithCustomError(c, 'CustomError').withArgs(errorNum); + //expect(c.testCustomViewRevert()).to.be.revertedWithCustomError(c, 'CustomError').withArgs(errorNum); + + it('Custom revert in view call', async () => { + // Perform view call, which is expected to revert + try { + await c.testCustomViewRevert(); + expect(false).to.be.true; + } + catch( x: any ) { + expect(x.errorArgs[0]).to.eq(ERROR_NUM); + expect(x.errorName).to.eq('CustomError'); + } + }); + + it('Custom error in tx', async () => { + // Perform transaction which is expected to revert + try { + const tx = await c.testCustomRevert(); + console.log('txhash', tx.hash); + await tx.wait(); + expect(false).to.be.true; + } + catch( x: any ) { + expect(x.data).eq('0x110b3655' + ERROR_NUM.slice(2)); + } + }); +}); From 0d3d95727d58f498f2ae69bd531d16db155e10a6 Mon Sep 17 00:00:00 2001 From: CedarMist <134699267+CedarMist@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:08:07 +0100 Subject: [PATCH 3/6] contracts: added revert checks with require(.., "reason") --- contracts/contracts/tests/SemanticTests.sol | 10 ++++++ contracts/test/semantics.ts | 38 +++++++++++++++++---- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/contracts/contracts/tests/SemanticTests.sol b/contracts/contracts/tests/SemanticTests.sol index 6948b036..71085855 100644 --- a/contracts/contracts/tests/SemanticTests.sol +++ b/contracts/contracts/tests/SemanticTests.sol @@ -21,4 +21,14 @@ contract SemanticTests { function testCustomViewRevert () external pure returns (uint) { revert CustomError(ERROR_NUM); } + + function testViewRevert () external pure returns (uint) { + require(false, "ThisIsAnError"); + return ERROR_NUM; + } + + function testRevert () external { + x += 1; + require(false, "ThisIsAnError"); + } } \ No newline at end of file diff --git a/contracts/test/semantics.ts b/contracts/test/semantics.ts index c23bb5ed..427c6888 100644 --- a/contracts/test/semantics.ts +++ b/contracts/test/semantics.ts @@ -9,18 +9,23 @@ const ERROR_NUM = '0x1023456789abcdef1023456789abcdef1023456789abcdef1023456789a describe('EVM Semantics', () => { let c: SemanticTests; + let chainId: number; + before(async () => { const f = await ethers.getContractFactory('SemanticTests') as SemanticTests__factory; c = await f.deploy(); await c.deployed(); + chainId = (await c.provider.getNetwork()).chainId }); it('eth_call maximum return length vs gas limit', async () => { - const i = 1787872; - const respHex = await c.testViewLength(i); - const respBytes = ethers.utils.arrayify(respHex); - expect(respBytes.length).eq(i); - expect(c.testViewLength(i+1)).reverted; + if( chainId != 31337 ) { + const i = 1787872; + const respHex = await c.testViewLength(i); + const respBytes = ethers.utils.arrayify(respHex); + expect(respBytes.length).eq(i); + expect(c.testViewLength(i+1)).reverted; + } }); // Apparently `expect().to.be.revertedWithCustomError` doesn't work sometimes @@ -28,6 +33,28 @@ describe('EVM Semantics', () => { //expect(c.testCustomRevert()).to.be.revertedWithCustomError(c, 'CustomError').withArgs(errorNum); //expect(c.testCustomViewRevert()).to.be.revertedWithCustomError(c, 'CustomError').withArgs(errorNum); + it('Error string in view call', async () => { + try { + await c.testViewRevert(); + } + catch( x: any ) { + expect(x.errorArgs[0]).to.eq('ThisIsAnError'); + expect(x.errorName).to.eq('Error'); + } + }); + + it('Error string in tx', async () => { + // Perform transaction which is expected to revert + try { + const tx = await c.testRevert(); + await tx.wait(); + expect(false).to.be.true; + } + catch( x: any ) { + expect(x.data).eq('0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d546869734973416e4572726f7200000000000000000000000000000000000000'); + } + }); + it('Custom revert in view call', async () => { // Perform view call, which is expected to revert try { @@ -44,7 +71,6 @@ describe('EVM Semantics', () => { // Perform transaction which is expected to revert try { const tx = await c.testCustomRevert(); - console.log('txhash', tx.hash); await tx.wait(); expect(false).to.be.true; } From 66c8ab8df5dd0ec7408270c6e176445f54ff7c0d Mon Sep 17 00:00:00 2001 From: CedarMist <134699267+CedarMist@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:18:14 +0100 Subject: [PATCH 4/6] contracts: format --- contracts/contracts/tests/SemanticTests.sol | 20 +-- contracts/test/semantics.ts | 129 ++++++++++---------- 2 files changed, 75 insertions(+), 74 deletions(-) diff --git a/contracts/contracts/tests/SemanticTests.sol b/contracts/contracts/tests/SemanticTests.sol index 71085855..c9376cfd 100644 --- a/contracts/contracts/tests/SemanticTests.sol +++ b/contracts/contracts/tests/SemanticTests.sol @@ -3,32 +3,32 @@ pragma solidity ^0.8.0; contract SemanticTests { - function testViewLength (uint256 len) external pure returns (bytes memory) - { + function testViewLength(uint256 len) external pure returns (bytes memory) { return new bytes(len); } - error CustomError(uint value); - uint private x; + error CustomError(uint256 value); + uint256 private x; - uint constant ERROR_NUM = 0x1023456789abcdef1023456789abcdef1023456789abcdef1023456789abcdef; + uint256 constant ERROR_NUM = + 0x1023456789abcdef1023456789abcdef1023456789abcdef1023456789abcdef; - function testCustomRevert () external { + function testCustomRevert() external { x += 1; revert CustomError(ERROR_NUM); } - function testCustomViewRevert () external pure returns (uint) { + function testCustomViewRevert() external pure returns (uint256) { revert CustomError(ERROR_NUM); } - function testViewRevert () external pure returns (uint) { + function testViewRevert() external pure returns (uint256) { require(false, "ThisIsAnError"); return ERROR_NUM; } - function testRevert () external { + function testRevert() external { x += 1; require(false, "ThisIsAnError"); } -} \ No newline at end of file +} diff --git a/contracts/test/semantics.ts b/contracts/test/semantics.ts index 427c6888..8c399ae4 100644 --- a/contracts/test/semantics.ts +++ b/contracts/test/semantics.ts @@ -5,77 +5,78 @@ import { expect } from 'chai'; import { SemanticTests } from '../typechain-types/contracts/tests/SemanticTests'; import { SemanticTests__factory } from '../typechain-types/factories/contracts/tests'; -const ERROR_NUM = '0x1023456789abcdef1023456789abcdef1023456789abcdef1023456789abcdef'; +const ERROR_NUM = + '0x1023456789abcdef1023456789abcdef1023456789abcdef1023456789abcdef'; describe('EVM Semantics', () => { - let c: SemanticTests; - let chainId: number; + let c: SemanticTests; + let chainId: number; - before(async () => { - const f = await ethers.getContractFactory('SemanticTests') as SemanticTests__factory; - c = await f.deploy(); - await c.deployed(); - chainId = (await c.provider.getNetwork()).chainId - }); + before(async () => { + const f = (await ethers.getContractFactory( + 'SemanticTests', + )) as SemanticTests__factory; + c = await f.deploy(); + await c.deployed(); + chainId = (await c.provider.getNetwork()).chainId; + }); - it('eth_call maximum return length vs gas limit', async () => { - if( chainId != 31337 ) { - const i = 1787872; - const respHex = await c.testViewLength(i); - const respBytes = ethers.utils.arrayify(respHex); - expect(respBytes.length).eq(i); - expect(c.testViewLength(i+1)).reverted; - } - }); + it('eth_call maximum return length vs gas limit', async () => { + if (chainId != 31337) { + const i = 1787872; + const respHex = await c.testViewLength(i); + const respBytes = ethers.utils.arrayify(respHex); + expect(respBytes.length).eq(i); + expect(c.testViewLength(i + 1)).reverted; + } + }); - // Apparently `expect().to.be.revertedWithCustomError` doesn't work sometimes - // Otherwise we could do this: - //expect(c.testCustomRevert()).to.be.revertedWithCustomError(c, 'CustomError').withArgs(errorNum); - //expect(c.testCustomViewRevert()).to.be.revertedWithCustomError(c, 'CustomError').withArgs(errorNum); + // Apparently `expect().to.be.revertedWithCustomError` doesn't work sometimes + // Otherwise we could do this: + //expect(c.testCustomRevert()).to.be.revertedWithCustomError(c, 'CustomError').withArgs(errorNum); + //expect(c.testCustomViewRevert()).to.be.revertedWithCustomError(c, 'CustomError').withArgs(errorNum); - it('Error string in view call', async () => { - try { - await c.testViewRevert(); - } - catch( x: any ) { - expect(x.errorArgs[0]).to.eq('ThisIsAnError'); - expect(x.errorName).to.eq('Error'); - } - }); + it('Error string in view call', async () => { + try { + await c.testViewRevert(); + } catch (x: any) { + expect(x.errorArgs[0]).to.eq('ThisIsAnError'); + expect(x.errorName).to.eq('Error'); + } + }); - it('Error string in tx', async () => { - // Perform transaction which is expected to revert - try { - const tx = await c.testRevert(); - await tx.wait(); - expect(false).to.be.true; - } - catch( x: any ) { - expect(x.data).eq('0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d546869734973416e4572726f7200000000000000000000000000000000000000'); - } - }); + it('Error string in tx', async () => { + // Perform transaction which is expected to revert + try { + const tx = await c.testRevert(); + await tx.wait(); + expect(false).to.be.true; + } catch (x: any) { + expect(x.data).eq( + '0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d546869734973416e4572726f7200000000000000000000000000000000000000', + ); + } + }); - it('Custom revert in view call', async () => { - // Perform view call, which is expected to revert - try { - await c.testCustomViewRevert(); - expect(false).to.be.true; - } - catch( x: any ) { - expect(x.errorArgs[0]).to.eq(ERROR_NUM); - expect(x.errorName).to.eq('CustomError'); - } - }); + it('Custom revert in view call', async () => { + // Perform view call, which is expected to revert + try { + await c.testCustomViewRevert(); + expect(false).to.be.true; + } catch (x: any) { + expect(x.errorArgs[0]).to.eq(ERROR_NUM); + expect(x.errorName).to.eq('CustomError'); + } + }); - it('Custom error in tx', async () => { - // Perform transaction which is expected to revert - try { - const tx = await c.testCustomRevert(); - await tx.wait(); - expect(false).to.be.true; - } - catch( x: any ) { - expect(x.data).eq('0x110b3655' + ERROR_NUM.slice(2)); - } - }); + it('Custom error in tx', async () => { + // Perform transaction which is expected to revert + try { + const tx = await c.testCustomRevert(); + await tx.wait(); + expect(false).to.be.true; + } catch (x: any) { + expect(x.data).eq('0x110b3655' + ERROR_NUM.slice(2)); + } + }); }); From 419d64dfc380bbfa1db151f787ec866d2691dfe3 Mon Sep 17 00:00:00 2001 From: CedarMist <134699267+CedarMist@users.noreply.github.com> Date: Tue, 24 Oct 2023 20:27:50 +0100 Subject: [PATCH 5/6] contracts: removed confusing tx reversion tests --- contracts/test/semantics.ts | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/contracts/test/semantics.ts b/contracts/test/semantics.ts index 8c399ae4..bead64b5 100644 --- a/contracts/test/semantics.ts +++ b/contracts/test/semantics.ts @@ -31,11 +31,6 @@ describe('EVM Semantics', () => { } }); - // Apparently `expect().to.be.revertedWithCustomError` doesn't work sometimes - // Otherwise we could do this: - //expect(c.testCustomRevert()).to.be.revertedWithCustomError(c, 'CustomError').withArgs(errorNum); - //expect(c.testCustomViewRevert()).to.be.revertedWithCustomError(c, 'CustomError').withArgs(errorNum); - it('Error string in view call', async () => { try { await c.testViewRevert(); @@ -45,19 +40,6 @@ describe('EVM Semantics', () => { } }); - it('Error string in tx', async () => { - // Perform transaction which is expected to revert - try { - const tx = await c.testRevert(); - await tx.wait(); - expect(false).to.be.true; - } catch (x: any) { - expect(x.data).eq( - '0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d546869734973416e4572726f7200000000000000000000000000000000000000', - ); - } - }); - it('Custom revert in view call', async () => { // Perform view call, which is expected to revert try { @@ -68,15 +50,4 @@ describe('EVM Semantics', () => { expect(x.errorName).to.eq('CustomError'); } }); - - it('Custom error in tx', async () => { - // Perform transaction which is expected to revert - try { - const tx = await c.testCustomRevert(); - await tx.wait(); - expect(false).to.be.true; - } catch (x: any) { - expect(x.data).eq('0x110b3655' + ERROR_NUM.slice(2)); - } - }); }); From 45f15cddd7f15598a396dacf2d9f65d4bcb1d1e9 Mon Sep 17 00:00:00 2001 From: CedarMist <134699267+CedarMist@users.noreply.github.com> Date: Mon, 30 Oct 2023 17:01:23 +0000 Subject: [PATCH 6/6] contracts: semantics - removed hardhat if condition & testing artifact from hardhat.config.ts --- contracts/hardhat.config.ts | 2 +- contracts/test/semantics.ts | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index 67427a34..fd95dc01 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -64,7 +64,7 @@ const config: HardhatUserConfig = { chainId: 0x5aff, accounts: process.env.SAPPHIRE_TESTNET_PRIVATE_KEY ? [process.env.SAPPHIRE_TESTNET_PRIVATE_KEY] - : TEST_HDWALLET, + : [], }, 'sapphire-mainnet': { url: 'https://sapphire.oasis.io', diff --git a/contracts/test/semantics.ts b/contracts/test/semantics.ts index bead64b5..49a7817d 100644 --- a/contracts/test/semantics.ts +++ b/contracts/test/semantics.ts @@ -22,13 +22,11 @@ describe('EVM Semantics', () => { }); it('eth_call maximum return length vs gas limit', async () => { - if (chainId != 31337) { - const i = 1787872; - const respHex = await c.testViewLength(i); - const respBytes = ethers.utils.arrayify(respHex); - expect(respBytes.length).eq(i); - expect(c.testViewLength(i + 1)).reverted; - } + const i = 1787872; + const respHex = await c.testViewLength(i); + const respBytes = ethers.utils.arrayify(respHex); + expect(respBytes.length).eq(i); + expect(c.testViewLength(i + 1)).reverted; }); it('Error string in view call', async () => {