From 4de65fb724520b3fc353bf8d3fbefd5dc8f754c9 Mon Sep 17 00:00:00 2001 From: GuillemGarciaDev Date: Wed, 3 Sep 2025 13:07:33 +0200 Subject: [PATCH 1/4] feat(tests/solidity): cancun opcodes testing --- tests/solidity/init-node.sh | 7 ++ .../opcodes/contracts/CancunOpCodes.sol | 73 +++++++++++++++++++ .../suites/opcodes/contracts/Migrations.sol | 23 ++++++ .../opcodes/migrations/1_initial_migration.js | 7 ++ .../opcodes/migrations/2_opCodes_migration.js | 7 ++ tests/solidity/suites/opcodes/package.json | 26 +++++++ .../suites/opcodes/test/cancunOpCodes.js | 41 +++++++++++ .../solidity/suites/opcodes/truffle-config.js | 22 ++++++ tests/solidity/yarn.lock | 8 ++ 9 files changed, 214 insertions(+) create mode 100644 tests/solidity/suites/opcodes/contracts/CancunOpCodes.sol create mode 100644 tests/solidity/suites/opcodes/contracts/Migrations.sol create mode 100644 tests/solidity/suites/opcodes/migrations/1_initial_migration.js create mode 100644 tests/solidity/suites/opcodes/migrations/2_opCodes_migration.js create mode 100644 tests/solidity/suites/opcodes/package.json create mode 100644 tests/solidity/suites/opcodes/test/cancunOpCodes.js create mode 100644 tests/solidity/suites/opcodes/truffle-config.js diff --git a/tests/solidity/init-node.sh b/tests/solidity/init-node.sh index 1264b30f..4a8fc336 100755 --- a/tests/solidity/init-node.sh +++ b/tests/solidity/init-node.sh @@ -62,12 +62,18 @@ USER3_MNEMONIC="will wear settle write dance topic tape sea glory hotel oppose r USER4_KEY="user4" USER4_MNEMONIC="doll midnight silk carpet brush boring pluck office gown inquiry duck chief aim exit gain never tennis crime fragile ship cloud surface exotic patch" +SOLIDITY_KEY="solidity" +SOLIDITY_MNEMONIC="exercise green picture marriage cause bike credit electric elephant someone march civil radio spoon sail vacant crime man fat save inject into grab drill" + # Import keys from mnemonics echo "$VAL_MNEMONIC" | "$BINARY" keys add "$VAL_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" echo "$USER1_MNEMONIC" | "$BINARY" keys add "$USER1_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" echo "$USER2_MNEMONIC" | "$BINARY" keys add "$USER2_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" echo "$USER3_MNEMONIC" | "$BINARY" keys add "$USER3_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" echo "$USER4_MNEMONIC" | "$BINARY" keys add "$USER4_KEY" --recover --keyring-backend "$KEYRING" --algo "$KEYALGO" --home "$CHAINDIR" +if ! "$BINARY" keys show "$SOLIDITY_KEY" --home "$CHAINDIR" >/dev/null 2>&1; then + echo "$SOLIDITY_MNEMONIC" | "$BINARY" keys add "$SOLIDITY_KEY" --recover --algo "$KEYALGO" --home "$CHAINDIR" +fi # Set moniker and chain-id for Cosmos EVM (Moniker can be anything, chain-id must be an integer) "$BINARY" init "$MONIKER" --chain-id "$CHAINID" --home "$CHAINDIR" @@ -114,6 +120,7 @@ sed -i.bak 's/create_empty_blocks = true/create_empty_blocks = false/g' "$CONFIG "$BINARY" add-genesis-account "$("$BINARY" keys show "$USER2_KEY" -a --keyring-backend "$KEYRING" --home "$CHAINDIR")" 1000000apoa,1000000000000000000000000000token --keyring-backend "$KEYRING" --home "$CHAINDIR" "$BINARY" add-genesis-account "$("$BINARY" keys show "$USER3_KEY" -a --keyring-backend "$KEYRING" --home "$CHAINDIR")" 1000000apoa,1000000000000000000000000000token --keyring-backend "$KEYRING" --home "$CHAINDIR" "$BINARY" add-genesis-account "$("$BINARY" keys show "$USER4_KEY" -a --keyring-backend "$KEYRING" --home "$CHAINDIR")" 1000000apoa,1000000000000000000000000000token --keyring-backend "$KEYRING" --home "$CHAINDIR" +"$BINARY" add-genesis-account "$("$BINARY" keys show "$SOLIDITY_KEY" -a --home "$CHAINDIR")" 1000000apoa,1000000000000000000000000000token --home "$CHAINDIR" # set custom pruning settings if [ "$PRUNING" = "custom" ]; then diff --git a/tests/solidity/suites/opcodes/contracts/CancunOpCodes.sol b/tests/solidity/suites/opcodes/contracts/CancunOpCodes.sol new file mode 100644 index 00000000..e3343c68 --- /dev/null +++ b/tests/solidity/suites/opcodes/contracts/CancunOpCodes.sol @@ -0,0 +1,73 @@ +pragma solidity >=0.8.24; + +contract Test1 { + function isSameAddress(address a, address b) public returns(bool){ //Simply add the two arguments and return + if (a == b) return true; + return false; + } +} + +contract CancunOpCodes { + + Test1 test1; + + constructor() public { //Constructor function + test1 = new Test1(); //Create new "Test1" function + } + + modifier onlyOwner(address _owner) { + require(msg.sender == _owner); + _; + } + // Add a todo to the list + function test() public { + + // blobbasefee + assembly { pop(blobbasefee()) } + + // mcopy test + assembly { + // Allocate memory for source and destination + let src := mload(0x40) + let dest := add(src, 0x40) + // Store a value at src + mstore(src, 0x123456789abcdef0) + // mcopy(dest, src, 32) + mcopy(dest, src, 32) + // Check that the value was copied + if iszero(eq(mload(dest), 0x123456789abcdef0)) { + revert(0, 0) + } + } + + // tstore and tload test (transient storage) + assembly { + let key := 0x42 + let val := 0xdeadbeef + tstore(key, val) + let loaded := tload(key) + if iszero(eq(loaded, val)) { + revert(0, 0) + } + } + } + + function test_revert() public { + + //revert + assembly{ revert(0, 0) } + } + + function test_invalid() public { + + //revert + assembly{ invalid() } + } + + function test_stop() public { + + //revert + assembly{ stop() } + } + +} diff --git a/tests/solidity/suites/opcodes/contracts/Migrations.sol b/tests/solidity/suites/opcodes/contracts/Migrations.sol new file mode 100644 index 00000000..42fbe885 --- /dev/null +++ b/tests/solidity/suites/opcodes/contracts/Migrations.sol @@ -0,0 +1,23 @@ +pragma solidity >=0.8.24; + +contract Migrations { + address public owner; + uint public last_completed_migration; + + constructor() public { + owner = msg.sender; + } + + modifier restricted() { + if (msg.sender == owner) _; + } + + function setCompleted(uint completed) public restricted { + last_completed_migration = completed; + } + + function upgrade(address new_address) public restricted { + Migrations upgraded = Migrations(new_address); + upgraded.setCompleted(last_completed_migration); + } +} diff --git a/tests/solidity/suites/opcodes/migrations/1_initial_migration.js b/tests/solidity/suites/opcodes/migrations/1_initial_migration.js new file mode 100644 index 00000000..a1aa22a5 --- /dev/null +++ b/tests/solidity/suites/opcodes/migrations/1_initial_migration.js @@ -0,0 +1,7 @@ +/* eslint-disable no-undef */ + +const Migrations = artifacts.require('Migrations') + +module.exports = function (deployer) { + deployer.deploy(Migrations) +} diff --git a/tests/solidity/suites/opcodes/migrations/2_opCodes_migration.js b/tests/solidity/suites/opcodes/migrations/2_opCodes_migration.js new file mode 100644 index 00000000..b8c241ce --- /dev/null +++ b/tests/solidity/suites/opcodes/migrations/2_opCodes_migration.js @@ -0,0 +1,7 @@ +/* eslint-disable no-undef */ + +const OpCodes = artifacts.require('./CancunOpCodes.sol.sol') + +module.exports = function (deployer) { + deployer.deploy(OpCodes) +} diff --git a/tests/solidity/suites/opcodes/package.json b/tests/solidity/suites/opcodes/package.json new file mode 100644 index 00000000..037d5306 --- /dev/null +++ b/tests/solidity/suites/opcodes/package.json @@ -0,0 +1,26 @@ +{ + "name": "opcode", + "version": "1.0.0", + "author": "Go Ethereum", + "license": "GPL-3.0-or-later", + "scripts": { + "test-ganache": "yarn truffle test", + "test-cosmos": "yarn truffle test --network cosmos" + }, + "devDependencies": { + "truffle-assertions": "^0.9.2" + }, + "standard": { + "globals": [ + "artifacts", + "expect", + "contract", + "beforeEach", + "before", + "web3", + "it", + "assert", + "describe" + ] + } +} diff --git a/tests/solidity/suites/opcodes/test/cancunOpCodes.js b/tests/solidity/suites/opcodes/test/cancunOpCodes.js new file mode 100644 index 00000000..ce1322ff --- /dev/null +++ b/tests/solidity/suites/opcodes/test/cancunOpCodes.js @@ -0,0 +1,41 @@ +/* eslint-disable no-undef */ +/* eslint-disable no-unused-expressions */ + +const TodoList = artifacts.require('./CancunOpCodes.sol') +let contractInstance + +contract('CancunOpCodes.sol', () => { + beforeEach(async () => { + contractInstance = await TodoList.deployed() + }) + it('Should run the majority of opcodes without errors', async () => { + let error + try { + await contractInstance.test() + await contractInstance.test_stop() + } catch (err) { + error = err + } + expect(error).to.be.undefined + }) + + it('Should throw invalid op code', async () => { + let error + try { + await contractInstance.test_invalid() + } catch (err) { + error = err + } + expect(error).not.to.be.undefined + }) + + it('Should revert', async () => { + let error + try { + await contractInstance.test_revert() + } catch (err) { + error = err + } + expect(error).not.to.be.undefined + }) +}) diff --git a/tests/solidity/suites/opcodes/truffle-config.js b/tests/solidity/suites/opcodes/truffle-config.js new file mode 100644 index 00000000..699fd76b --- /dev/null +++ b/tests/solidity/suites/opcodes/truffle-config.js @@ -0,0 +1,22 @@ +module.exports = { + networks: { + // Development network is just left as truffle's default settings + cosmos: { + host: '127.0.0.1', // Localhost (default: none) + port: 8545, // Standard Ethereum port (default: none) + network_id: 1440002, // Any network (default: none) + gas: 8000000, // Increased gas limit for complex contracts + gasPrice: 0, // Set to 0 for test network + from: "0x5A7E818D849D4926CD2E2E05B8E934D05EE87A7C", // Address derived from the private key + accounts: [ + "0x36DC1E881F351CFE35B79E3ED27C8EE737DFD7B48A9F2D43887E25D2F87625CB" + ] + } + }, + compilers: { + solc: { + version: '0.8.24', + evmVersion: 'cancun' + } + } +} diff --git a/tests/solidity/yarn.lock b/tests/solidity/yarn.lock index b5bb5dd3..b0d476ee 100644 --- a/tests/solidity/yarn.lock +++ b/tests/solidity/yarn.lock @@ -9400,6 +9400,14 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +truffle-assertions@^0.9.2: + version "0.9.2" + resolved "https://registry.yarnpkg.com/truffle-assertions/-/truffle-assertions-0.9.2.tgz#0f8360f53ad92b6d8fdb8ceb5dce54c1fc392e23" + integrity sha512-9g2RhaxU2F8DeWhqoGQvL/bV8QVoSnQ6PY+ZPvYRP5eF7+/8LExb4mjLx/FeliLTjc3Tv1SABG05Gu5qQ/ErmA== + dependencies: + assertion-error "^1.1.0" + lodash.isequal "^4.5.0" + truffle@5.5.8: version "5.5.8" resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.5.8.tgz#79346b8478d87de1962b57c44dcd057658253716" From 9c7bc933acb71315e66bfd61a3fc5d0c97b02d4a Mon Sep 17 00:00:00 2001 From: GuillemGarciaDev Date: Wed, 3 Sep 2025 13:16:46 +0200 Subject: [PATCH 2/4] fix(tests/solidity/opcodes): rename package name --- tests/solidity/suites/opcodes/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/solidity/suites/opcodes/package.json b/tests/solidity/suites/opcodes/package.json index 037d5306..f222bf96 100644 --- a/tests/solidity/suites/opcodes/package.json +++ b/tests/solidity/suites/opcodes/package.json @@ -1,5 +1,5 @@ { - "name": "opcode", + "name": "opcodes ", "version": "1.0.0", "author": "Go Ethereum", "license": "GPL-3.0-or-later", From 02543a779f684bf696519b0175ae327f0432ad51 Mon Sep 17 00:00:00 2001 From: GuillemGarciaDev Date: Wed, 3 Sep 2025 14:04:25 +0200 Subject: [PATCH 3/4] feat(tests/solidity): test prague EIP-2537 --- .../opcodes/contracts/CancunOpCodes.sol | 17 ---- .../opcodes/contracts/PragueOpCodes.sol | 77 +++++++++++++++++++ .../opcodes/migrations/2_opCodes_migration.js | 8 +- tests/solidity/suites/opcodes/package.json | 2 +- .../suites/opcodes/test/pragueOpCodes.js | 41 ++++++++++ .../solidity/suites/opcodes/truffle-config.js | 8 +- 6 files changed, 131 insertions(+), 22 deletions(-) create mode 100644 tests/solidity/suites/opcodes/contracts/PragueOpCodes.sol create mode 100644 tests/solidity/suites/opcodes/test/pragueOpCodes.js diff --git a/tests/solidity/suites/opcodes/contracts/CancunOpCodes.sol b/tests/solidity/suites/opcodes/contracts/CancunOpCodes.sol index e3343c68..0e59866a 100644 --- a/tests/solidity/suites/opcodes/contracts/CancunOpCodes.sol +++ b/tests/solidity/suites/opcodes/contracts/CancunOpCodes.sol @@ -1,24 +1,7 @@ pragma solidity >=0.8.24; -contract Test1 { - function isSameAddress(address a, address b) public returns(bool){ //Simply add the two arguments and return - if (a == b) return true; - return false; - } -} - contract CancunOpCodes { - Test1 test1; - - constructor() public { //Constructor function - test1 = new Test1(); //Create new "Test1" function - } - - modifier onlyOwner(address _owner) { - require(msg.sender == _owner); - _; - } // Add a todo to the list function test() public { diff --git a/tests/solidity/suites/opcodes/contracts/PragueOpCodes.sol b/tests/solidity/suites/opcodes/contracts/PragueOpCodes.sol new file mode 100644 index 00000000..e2ca75cb --- /dev/null +++ b/tests/solidity/suites/opcodes/contracts/PragueOpCodes.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +pragma solidity >= 0.8.24; + +library BLS12381 { + address constant G1ADD = address(0x0b); + address constant G1MSM = address(0x0c); + address constant G2ADD = address(0x0d); + address constant G2MSM = address(0x0e); + address constant PAIRING = address(0x0f); + address constant MAP_G1 = address(0x10); + address constant MAP_G2 = address(0x11); + + function _pcall(address precompile, bytes memory input, uint outSize) + private view returns (bool ok, bytes memory out) + { + out = new bytes(outSize); + assembly { + ok := staticcall(gas(), precompile, add(input, 0x20), mload(input), add(out, 0x20), outSize) + } + } + + function mapToG1(bytes memory fp) internal view returns (bytes memory g1) { + (bool ok, bytes memory out) = _pcall(MAP_G1, fp, 128); + require(ok, "mapToG1 fail"); return out; + } + + function g1Add(bytes memory a, bytes memory b) internal view returns (bytes memory sum) { + bytes memory inbuf = bytes.concat(a, b); // 128 + 128 = 256 + (bool ok, bytes memory out) = _pcall(G1ADD, inbuf, 128); + require(ok, "g1Add fail"); return out; + } + + function pairing(bytes memory inbuf) internal view returns (bool) { + (bool ok, bytes memory out) = _pcall(PAIRING, inbuf, 32); + require(ok, "pairing fail"); + return out[31] == 0x01; + } +} + +contract PragueOpCodes { + using BLS12381 for bytes; + + // 64 zero bytes (a valid Fp element) + bytes constant FP_ZERO = hex"0000000000000000000000000000000000000000000000000000000000000000"; + + // 128 zero bytes (G1/G2 infinity encodings) + bytes constant G1_INFINITY = hex"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + bytes constant G2_INFINITY = hex"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; // 256B + + function test() public { + // BLS12381 + bytes memory P = BLS12381.mapToG1(FP_ZERO); + bytes memory S = BLS12381.g1Add(P, G1_INFINITY); + require(keccak256(S) == keccak256(P), "error"); + + bytes memory inbuf = bytes.concat(G1_INFINITY, G2_INFINITY); + require(BLS12381.pairing(inbuf), "error pairing"); + } + + function test_revert() public { + + //revert + assembly{ revert(0, 0) } + } + + function test_invalid() public { + + //revert + assembly{ invalid() } + } + + function test_stop() public { + + //revert + assembly{ stop() } + } +} diff --git a/tests/solidity/suites/opcodes/migrations/2_opCodes_migration.js b/tests/solidity/suites/opcodes/migrations/2_opCodes_migration.js index b8c241ce..bbffa1e6 100644 --- a/tests/solidity/suites/opcodes/migrations/2_opCodes_migration.js +++ b/tests/solidity/suites/opcodes/migrations/2_opCodes_migration.js @@ -1,7 +1,9 @@ /* eslint-disable no-undef */ -const OpCodes = artifacts.require('./CancunOpCodes.sol.sol') +const CancunOpCodes = artifacts.require('./CancunOpCodes.sol') +const PragueOpCodes = artifacts.require('./PragueOpCodes.sol') -module.exports = function (deployer) { - deployer.deploy(OpCodes) +module.exports = async function (deployer) { + await deployer.deploy(CancunOpCodes) + await deployer.deploy(PragueOpCodes) } diff --git a/tests/solidity/suites/opcodes/package.json b/tests/solidity/suites/opcodes/package.json index f222bf96..a20d8f89 100644 --- a/tests/solidity/suites/opcodes/package.json +++ b/tests/solidity/suites/opcodes/package.json @@ -1,5 +1,5 @@ { - "name": "opcodes ", + "name": "opcodes", "version": "1.0.0", "author": "Go Ethereum", "license": "GPL-3.0-or-later", diff --git a/tests/solidity/suites/opcodes/test/pragueOpCodes.js b/tests/solidity/suites/opcodes/test/pragueOpCodes.js new file mode 100644 index 00000000..17cd0779 --- /dev/null +++ b/tests/solidity/suites/opcodes/test/pragueOpCodes.js @@ -0,0 +1,41 @@ +/* eslint-disable no-undef */ +/* eslint-disable no-unused-expressions */ + +const TodoList = artifacts.require('./PragueOpCodes.sol') +let contractInstance + +contract('PragueOpCodes.sol', () => { + beforeEach(async () => { + contractInstance = await TodoList.deployed() + }) + it('Should run the majority of opcodes without errors', async () => { + let error + try { + await contractInstance.test() + await contractInstance.test_stop() + } catch (err) { + error = err + } + expect(error).to.be.undefined + }) + + it('Should throw invalid op code', async () => { + let error + try { + await contractInstance.test_invalid() + } catch (err) { + error = err + } + expect(error).not.to.be.undefined + }) + + it('Should revert', async () => { + let error + try { + await contractInstance.test_revert() + } catch (err) { + error = err + } + expect(error).not.to.be.undefined + }) +}) diff --git a/tests/solidity/suites/opcodes/truffle-config.js b/tests/solidity/suites/opcodes/truffle-config.js index 699fd76b..cff7848c 100644 --- a/tests/solidity/suites/opcodes/truffle-config.js +++ b/tests/solidity/suites/opcodes/truffle-config.js @@ -16,7 +16,13 @@ module.exports = { compilers: { solc: { version: '0.8.24', - evmVersion: 'cancun' + settings: { + evmVersion: 'cancun', + optimizer: { + enabled: false + }, + viaIR: false + } } } } From f09ba13d620af52867fadac42aace29db4addcaf Mon Sep 17 00:00:00 2001 From: GuillemGarciaDev Date: Tue, 9 Sep 2025 10:55:19 +0200 Subject: [PATCH 4/4] fix: remove upgrade tests and add solidity test --- Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b583ae7e..7629984b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,10 +20,11 @@ RUN make lint RUN make test-poa # Integration tests RUN make test-integration -RUN make test-upgrade # Simulation tests RUN make test-sim-benchmark-simulation RUN make test-sim-full-app-fast +# Solidity tests +RUN make test-solidity RUN touch /test.lock