diff --git a/rskj-core/src/main/java/org/ethereum/config/blockchain/upgrades/ConsensusRule.java b/rskj-core/src/main/java/org/ethereum/config/blockchain/upgrades/ConsensusRule.java index ca8d4c006ad..b2a6ce9b0b6 100644 --- a/rskj-core/src/main/java/org/ethereum/config/blockchain/upgrades/ConsensusRule.java +++ b/rskj-core/src/main/java/org/ethereum/config/blockchain/upgrades/ConsensusRule.java @@ -100,8 +100,9 @@ public enum ConsensusRule { RSKIP434("rskip434"), RSKIP438("rskip438"), RSKIP445("rskip445"), // From EIP-5656 MCOPY instruction + RSKIP446("rskip446") ,// Transient storage opcodes addition implementing EIP-1153 RSKIP453("rskip453"), - RSKIP454("rskip454"), + RSKIP454("rskip454") ; private final String configKey; diff --git a/rskj-core/src/main/java/org/ethereum/core/Repository.java b/rskj-core/src/main/java/org/ethereum/core/Repository.java index 0cf1bfa183d..38b10af2f68 100644 --- a/rskj-core/src/main/java/org/ethereum/core/Repository.java +++ b/rskj-core/src/main/java/org/ethereum/core/Repository.java @@ -27,7 +27,7 @@ import java.math.BigInteger; -public interface Repository extends RepositorySnapshot { +public interface Repository extends RepositorySnapshot, TransientRepository { Trie getTrie(); /** diff --git a/rskj-core/src/main/java/org/ethereum/core/TransactionExecutor.java b/rskj-core/src/main/java/org/ethereum/core/TransactionExecutor.java index 10b7f48bf8d..bd026d1f10c 100644 --- a/rskj-core/src/main/java/org/ethereum/core/TransactionExecutor.java +++ b/rskj-core/src/main/java/org/ethereum/core/TransactionExecutor.java @@ -583,6 +583,8 @@ private void finalization() { // Traverse list of suicides result.getDeleteAccounts().forEach(address -> track.delete(new RskAddress(address))); + track.clearTransientStorage(); + logger.trace("tx listener done"); logger.trace("tx finalization done"); diff --git a/rskj-core/src/main/java/org/ethereum/core/TransientRepository.java b/rskj-core/src/main/java/org/ethereum/core/TransientRepository.java new file mode 100644 index 00000000000..eee1f29d4ab --- /dev/null +++ b/rskj-core/src/main/java/org/ethereum/core/TransientRepository.java @@ -0,0 +1,40 @@ +/* + * This file is part of RskJ + * Copyright (C) 2024 RSK Labs Ltd. + * (derived from ethereumJ library, Copyright (c) 2016 ) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package org.ethereum.core; + +import co.rsk.core.RskAddress; +import org.ethereum.vm.DataWord; + +import javax.annotation.Nullable; + +public interface TransientRepository { + + void addTransientStorageRow(RskAddress addr, DataWord key, DataWord value); + + void addTransientStorageBytes(RskAddress addr, DataWord key, byte[] value); + + void clearTransientStorage(); + + @Nullable + DataWord getTransientStorageValue(RskAddress addr, DataWord key); + + @Nullable + byte[] getTransientStorageBytes(RskAddress addr, DataWord key); +} \ No newline at end of file diff --git a/rskj-core/src/main/java/org/ethereum/db/MutableRepository.java b/rskj-core/src/main/java/org/ethereum/db/MutableRepository.java index 42dd7336b25..f92bf4a9eee 100644 --- a/rskj-core/src/main/java/org/ethereum/db/MutableRepository.java +++ b/rskj-core/src/main/java/org/ethereum/db/MutableRepository.java @@ -25,19 +25,29 @@ import co.rsk.crypto.Keccak256; import co.rsk.db.MutableTrieCache; import co.rsk.db.MutableTrieImpl; -import co.rsk.trie.*; +import co.rsk.trie.IterationElement; +import co.rsk.trie.MutableTrie; +import co.rsk.trie.Trie; +import co.rsk.trie.TrieKeySlice; +import co.rsk.trie.TrieStore; +import co.rsk.trie.TrieStoreImpl; import com.google.common.annotations.VisibleForTesting; import org.ethereum.core.AccountState; import org.ethereum.core.Repository; import org.ethereum.crypto.HashUtil; import org.ethereum.crypto.Keccak256Helper; +import org.ethereum.datasource.HashMapDB; import org.ethereum.vm.DataWord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.math.BigInteger; -import java.util.*; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Optional; +import java.util.Set; public class MutableRepository implements Repository { private static final Logger logger = LoggerFactory.getLogger("repository"); @@ -47,21 +57,36 @@ public class MutableRepository implements Repository { private final TrieKeyMapper trieKeyMapper; private final MutableTrie mutableTrie; + private MutableTrie transientTrie; private final IReadWrittenKeysTracker tracker; public MutableRepository(TrieStore trieStore, Trie trie) { - this(new MutableTrieImpl(trieStore, trie)); + this(new MutableTrieImpl(trieStore, trie), aInMemoryMutableTrie()); } public MutableRepository(MutableTrie mutableTrie) { + this(mutableTrie, aInMemoryMutableTrie()); + } + + public MutableRepository(MutableTrie mutableTrie, IReadWrittenKeysTracker tracker) { + this(mutableTrie, aInMemoryMutableTrie(), tracker); + } + + private static MutableTrieImpl aInMemoryMutableTrie() { + return new MutableTrieImpl(new TrieStoreImpl(new HashMapDB()), new Trie()); + } + + public MutableRepository(MutableTrie mutableTrie, MutableTrie transientTrie) { this.trieKeyMapper = new TrieKeyMapper(); this.mutableTrie = mutableTrie; + this.transientTrie = transientTrie; this.tracker = new DummyReadWrittenKeysTracker(); } - public MutableRepository(MutableTrie mutableTrie, IReadWrittenKeysTracker tracker) { + public MutableRepository(MutableTrie mutableTrie, MutableTrie transientTrie, IReadWrittenKeysTracker tracker) { this.trieKeyMapper = new TrieKeyMapper(); this.mutableTrie = mutableTrie; + this.transientTrie = transientTrie; this.tracker = tracker; } @@ -327,7 +352,7 @@ public synchronized Set getAccountsKeys() { // To start tracking, a new repository is created, with a MutableTrieCache in the middle @Override public synchronized Repository startTracking() { - return new MutableRepository(new MutableTrieCache(mutableTrie), tracker); + return new MutableRepository(new MutableTrieCache(mutableTrie), new MutableTrieCache(transientTrie), tracker); } @Override @@ -338,11 +363,13 @@ public void save() { @Override public synchronized void commit() { mutableTrie.commit(); + transientTrie.commit(); } @Override public synchronized void rollback() { mutableTrie.rollback(); + transientTrie.rollback(); } @Override @@ -406,4 +433,47 @@ private Optional internalGetValueHash(byte[] key) { tracker.addNewReadKey(new ByteArrayWrapper(key)); return mutableTrie.getValueHash(key); } + + @Override + public void addTransientStorageRow(RskAddress addr, DataWord key, DataWord value) { + addTransientStorageBytes(addr, key, value.getByteArrayForStorage()); + } + + @Override + public void addTransientStorageBytes(RskAddress addr, DataWord key, byte[] value) { + byte[] triekey = trieKeyMapper.getAccountStorageKey(addr, key); + + // Special case: if the value is an empty vector, we pass "null" which commands the trie to remove the item. + // Note that if the call comes from addTransientStorageRow(), this method will already have replaced 0 by null, so the + // conversion here only applies if this is called directly. If suppose this only occurs in tests, but it can + // also occur in precompiled contracts that store data directly using this method. + if (value == null || value.length == 0) { + transientTrie.put(triekey, null); + } else { + transientTrie.put(triekey, value); + } + } + + @Override + public void clearTransientStorage() { + this.transientTrie = aInMemoryMutableTrie(); + } + + @Nullable + @Override + public DataWord getTransientStorageValue(RskAddress addr, DataWord key) { + byte[] value = getTransientStorageBytes(addr, key); + if (value == null) { + return null; + } + + return DataWord.valueOf(value); + } + + @Nullable + @Override + public byte[] getTransientStorageBytes(RskAddress addr, DataWord key) { + byte[] triekey = trieKeyMapper.getAccountStorageKey(addr, key); + return transientTrie.get(triekey); + } } diff --git a/rskj-core/src/main/java/org/ethereum/vm/GasCost.java b/rskj-core/src/main/java/org/ethereum/vm/GasCost.java index c9da2ebc095..c9c786841ff 100644 --- a/rskj-core/src/main/java/org/ethereum/vm/GasCost.java +++ b/rskj-core/src/main/java/org/ethereum/vm/GasCost.java @@ -61,6 +61,9 @@ public class GasCost { public static final long REFUND_SSTORE = 15000; public static final long CREATE = 32000; + public static final long TLOAD = 100; + public static final long TSTORE = 100; + public static final long JUMPDEST = 1; public static final long CREATE_DATA_BYTE = 5; public static final long CALL = 700; diff --git a/rskj-core/src/main/java/org/ethereum/vm/OpCode.java b/rskj-core/src/main/java/org/ethereum/vm/OpCode.java index 52008f8fefd..0204af6e2ec 100644 --- a/rskj-core/src/main/java/org/ethereum/vm/OpCode.java +++ b/rskj-core/src/main/java/org/ethereum/vm/OpCode.java @@ -333,6 +333,16 @@ public enum OpCode { */ MCOPY(0x5e, 3, 0, VERY_LOW_TIER), + /** + * (0x5c) Load word from transient storage at address + */ + TLOAD(0x5c, 1, 1, SPECIAL_TIER), // Will adjust the correct inputs and outputs later + + /** + * (0x5c) Store word from transient storage at address + */ + TSTORE(0x5d, 2, 0, SPECIAL_TIER), // Will adjust the correct inputs and outputs later + /* Push Operations */ /** * (0x5f) Pushes the constant value 0 onto the stack. diff --git a/rskj-core/src/main/java/org/ethereum/vm/OpCodes.java b/rskj-core/src/main/java/org/ethereum/vm/OpCodes.java index 822e9f03185..16f84d945b3 100644 --- a/rskj-core/src/main/java/org/ethereum/vm/OpCodes.java +++ b/rskj-core/src/main/java/org/ethereum/vm/OpCodes.java @@ -329,6 +329,14 @@ private OpCodes() { * (0x5e) */ public static final byte OP_MCOPY = 0x5e; + /** + * (0x5c) + */ + public static final byte OP_TLOAD =0x5c ; + /** + * (0x5d) + */ + public static final byte OP_TSTORE =0x5d ; /* Push Operations */ /** diff --git a/rskj-core/src/main/java/org/ethereum/vm/VM.java b/rskj-core/src/main/java/org/ethereum/vm/VM.java index 45aa797f4ed..1c9537ccd6f 100644 --- a/rskj-core/src/main/java/org/ethereum/vm/VM.java +++ b/rskj-core/src/main/java/org/ethereum/vm/VM.java @@ -42,7 +42,21 @@ import java.util.Iterator; import java.util.List; -import static org.ethereum.config.blockchain.upgrades.ConsensusRule.*; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP103; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP120; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP125; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP140; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP150; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP151; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP152; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP169; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP191; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP398; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP412; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP445; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP446; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP90; +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP91; import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY; import static org.ethereum.vm.OpCode.CALL; @@ -50,37 +64,37 @@ /** * The Ethereum Virtual Machine (EVM) is responsible for initialization * and executing a transaction on a contract. - * + * It is a quasi-Turing-complete machine; the quasi qualification * comes from the fact that the computation is intrinsically bounded * through a parameter, gas, which limits the total amount of computation done. - * + * The EVM is a simple stack-based architecture. The word size of the machine * (and thus size of stack item) is 256-bit. This was chosen to facilitate * the SHA3-256 hash scheme and elliptic-curve computations. The memory model * is a simple word-addressed byte array. The stack has an unlimited size. * The machine also has an independent storage model; this is similar in concept * to the memory but rather than a byte array, it is a word-addressable word array. - * + * Unlike memory, which is volatile, storage is non volatile and is * maintained as part of the system state. All locations in both storage * and memory are well-defined initially as zero. - * + * The machine does not follow the standard von Neumann architecture. * Rather than storing program code in generally-accessible memory or storage, * it is stored separately in a virtual ROM interactable only though * a specialised instruction. - * + * The machine can have exceptional execution for several reasons, * including stack underflows and invalid instructions. These unambiguously * and validly result in immediate halting of the machine with all state changes * left intact. The one piece of exceptional execution that does not leave * state changes intact is the out-of-gas (OOG) exception. - * + * Here, the machine halts immediately and reports the issue to * the execution agent (either the transaction processor or, recursively, * the spawning execution environment) and which will deal with it separately. - * + * @author Roman Mandeleil * @since 01.06.2014 */ @@ -1345,6 +1359,48 @@ else if (oldValue != null && newValue.isZero()) { program.step(); } + protected void doTLOAD(){ + if (computeGas) { + gasCost = GasCost.TLOAD; + spendOpCodeGas(); + } + + DataWord key = program.stackPop(); + if (isLogEnabled) { + logger.info("Executing TLOAD with parameters: key = {}", key); + } + DataWord val = program.transientStorageLoad(key); + + if (val == null) { + val = DataWord.ZERO; + } + + program.stackPush(val); + // key could be returned to the pool, but transientStorageLoad semantics should be checked + // to make sure storageLoad always gets a copy, not a reference. + program.step(); + } + + protected void doTSTORE(){ + if (computeGas) { + gasCost = GasCost.TSTORE; + spendOpCodeGas(); + } + + if (program.isStaticCall()) { + throw Program.ExceptionHelper.modificationException(program); + } + + DataWord key = program.stackPop(); + DataWord value = program.stackPop(); + + if (isLogEnabled) { + logger.info("Executing TSTORE with parameters: address={} | value = {}", key, value); + } + program.transientStorageSave(key, value); + program.step(); + } + protected void doJUMP(){ spendOpCodeGas(); // EXECUTION PHASE @@ -1853,14 +1909,15 @@ protected void executeOpcode() { break; case OpCodes.OP_CALLDATACOPY: doCALLDATACOPY(); break; - case OpCodes.OP_CODESIZE: - case OpCodes.OP_EXTCODESIZE: doCODESIZE(); + case OpCodes.OP_CODESIZE, + OpCodes.OP_EXTCODESIZE: + doCODESIZE(); break; - case OpCodes.OP_CODECOPY: - case OpCodes.OP_EXTCODECOPY: doCODECOPY(); + case OpCodes.OP_CODECOPY, + OpCodes.OP_EXTCODECOPY: + doCODECOPY(); break; - case OpCodes.OP_EXTCODEHASH: if (!activations.isActive(RSKIP140)) { throw Program.ExceptionHelper.invalidOpCode(program); @@ -1918,39 +1975,41 @@ protected void executeOpcode() { case OpCodes.OP_POP: doPOP(); break; - case OpCodes.OP_DUP_1: - case OpCodes.OP_DUP_2: - case OpCodes.OP_DUP_3: - case OpCodes.OP_DUP_4: - case OpCodes.OP_DUP_5: - case OpCodes.OP_DUP_6: - case OpCodes.OP_DUP_7: - case OpCodes.OP_DUP_8: - case OpCodes.OP_DUP_9: - case OpCodes.OP_DUP_10: - case OpCodes.OP_DUP_11: - case OpCodes.OP_DUP_12: - case OpCodes.OP_DUP_13: - case OpCodes.OP_DUP_14: - case OpCodes.OP_DUP_15: - case OpCodes.OP_DUP_16: doDUP(); - break; - case OpCodes.OP_SWAP_1: - case OpCodes.OP_SWAP_2: - case OpCodes.OP_SWAP_3: - case OpCodes.OP_SWAP_4: - case OpCodes.OP_SWAP_5: - case OpCodes.OP_SWAP_6: - case OpCodes.OP_SWAP_7: - case OpCodes.OP_SWAP_8: - case OpCodes.OP_SWAP_9: - case OpCodes.OP_SWAP_10: - case OpCodes.OP_SWAP_11: - case OpCodes.OP_SWAP_12: - case OpCodes.OP_SWAP_13: - case OpCodes.OP_SWAP_14: - case OpCodes.OP_SWAP_15: - case OpCodes.OP_SWAP_16: doSWAP(); + case OpCodes.OP_DUP_1 , + OpCodes.OP_DUP_2 , + OpCodes.OP_DUP_3 , + OpCodes.OP_DUP_4 , + OpCodes.OP_DUP_5 , + OpCodes.OP_DUP_6 , + OpCodes.OP_DUP_7 , + OpCodes.OP_DUP_8 , + OpCodes.OP_DUP_9 , + OpCodes.OP_DUP_10 , + OpCodes.OP_DUP_11 , + OpCodes.OP_DUP_12 , + OpCodes.OP_DUP_13 , + OpCodes.OP_DUP_14 , + OpCodes.OP_DUP_15 , + OpCodes.OP_DUP_16: + doDUP(); + break; + case OpCodes.OP_SWAP_1, + OpCodes.OP_SWAP_2, + OpCodes.OP_SWAP_3, + OpCodes.OP_SWAP_4, + OpCodes.OP_SWAP_5, + OpCodes.OP_SWAP_6, + OpCodes.OP_SWAP_7, + OpCodes.OP_SWAP_8, + OpCodes.OP_SWAP_9, + OpCodes.OP_SWAP_10, + OpCodes.OP_SWAP_11, + OpCodes.OP_SWAP_12, + OpCodes.OP_SWAP_13, + OpCodes.OP_SWAP_14, + OpCodes.OP_SWAP_15, + OpCodes.OP_SWAP_16: + doSWAP(); break; case OpCodes.OP_SWAPN: if (activations.isActive(RSKIP191)) { @@ -1961,11 +2020,12 @@ protected void executeOpcode() { break; - case OpCodes.OP_LOG_0: - case OpCodes.OP_LOG_1: - case OpCodes.OP_LOG_2: - case OpCodes.OP_LOG_3: - case OpCodes.OP_LOG_4: doLOG(); + case OpCodes.OP_LOG_0, + OpCodes.OP_LOG_1, + OpCodes.OP_LOG_2, + OpCodes.OP_LOG_3, + OpCodes.OP_LOG_4: + doLOG(); break; case OpCodes.OP_MLOAD: doMLOAD(); break; @@ -1976,7 +2036,19 @@ protected void executeOpcode() { case OpCodes.OP_SLOAD: doSLOAD(); break; case OpCodes.OP_SSTORE: doSSTORE(); - break; + break; + case OpCodes.OP_TLOAD: + if (!activations.isActive(RSKIP446)) { + throw Program.ExceptionHelper.invalidOpCode(program); + } + doTLOAD(); + break; + case OpCodes.OP_TSTORE: + if (!activations.isActive(RSKIP446)) { + throw Program.ExceptionHelper.invalidOpCode(program); + } + doTSTORE(); + break; case OpCodes.OP_JUMP: doJUMP(); break; case OpCodes.OP_JUMPI: doJUMPI(); @@ -1995,38 +2067,39 @@ protected void executeOpcode() { doPUSH0(); break; - case OpCodes.OP_PUSH_1: - case OpCodes.OP_PUSH_2: - case OpCodes.OP_PUSH_3: - case OpCodes.OP_PUSH_4: - case OpCodes.OP_PUSH_5: - case OpCodes.OP_PUSH_6: - case OpCodes.OP_PUSH_7: - case OpCodes.OP_PUSH_8: - case OpCodes.OP_PUSH_9: - case OpCodes.OP_PUSH_10: - case OpCodes.OP_PUSH_11: - case OpCodes.OP_PUSH_12: - case OpCodes.OP_PUSH_13: - case OpCodes.OP_PUSH_14: - case OpCodes.OP_PUSH_15: - case OpCodes.OP_PUSH_16: - case OpCodes.OP_PUSH_17: - case OpCodes.OP_PUSH_18: - case OpCodes.OP_PUSH_19: - case OpCodes.OP_PUSH_20: - case OpCodes.OP_PUSH_21: - case OpCodes.OP_PUSH_22: - case OpCodes.OP_PUSH_23: - case OpCodes.OP_PUSH_24: - case OpCodes.OP_PUSH_25: - case OpCodes.OP_PUSH_26: - case OpCodes.OP_PUSH_27: - case OpCodes.OP_PUSH_28: - case OpCodes.OP_PUSH_29: - case OpCodes.OP_PUSH_30: - case OpCodes.OP_PUSH_31: - case OpCodes.OP_PUSH_32: doPUSH(); + case OpCodes.OP_PUSH_1, + OpCodes.OP_PUSH_2, + OpCodes.OP_PUSH_3, + OpCodes.OP_PUSH_4, + OpCodes.OP_PUSH_5, + OpCodes.OP_PUSH_6, + OpCodes.OP_PUSH_7, + OpCodes.OP_PUSH_8, + OpCodes.OP_PUSH_9, + OpCodes.OP_PUSH_10, + OpCodes.OP_PUSH_11, + OpCodes.OP_PUSH_12, + OpCodes.OP_PUSH_13, + OpCodes.OP_PUSH_14, + OpCodes.OP_PUSH_15, + OpCodes.OP_PUSH_16, + OpCodes.OP_PUSH_17, + OpCodes.OP_PUSH_18, + OpCodes.OP_PUSH_19, + OpCodes.OP_PUSH_20, + OpCodes.OP_PUSH_21, + OpCodes.OP_PUSH_22, + OpCodes.OP_PUSH_23, + OpCodes.OP_PUSH_24, + OpCodes.OP_PUSH_25, + OpCodes.OP_PUSH_26, + OpCodes.OP_PUSH_27, + OpCodes.OP_PUSH_28, + OpCodes.OP_PUSH_29, + OpCodes.OP_PUSH_30, + OpCodes.OP_PUSH_31, + OpCodes.OP_PUSH_32: + doPUSH(); break; case OpCodes.OP_JUMPDEST: doJUMPDEST(); break; @@ -2044,10 +2117,10 @@ protected void executeOpcode() { } doCREATE2(); break; - case OpCodes.OP_CALL: - case OpCodes.OP_CALLCODE: - case OpCodes.OP_DELEGATECALL: - doCALL(); + case OpCodes.OP_CALL, + OpCodes.OP_CALLCODE, + OpCodes.OP_DELEGATECALL: + doCALL(); break; case OpCodes.OP_STATICCALL: if (!activations.isActive(RSKIP91)) { @@ -2214,9 +2287,7 @@ private void dumpLine(OpCode op, long gasBefore, long gasCost, long memWords, Pr RskAddress ownerAddress = new RskAddress(program.getOwnerAddress()); if ("standard+".equals(vmConfig.dumpStyle())) { switch (op) { - case STOP: - case RETURN: - case SUICIDE: + case STOP, RETURN, SUICIDE: Iterator keysIterator = storage.getStorageKeys(ownerAddress); while (keysIterator.hasNext()) { DataWord key = keysIterator.next(); diff --git a/rskj-core/src/main/java/org/ethereum/vm/program/Program.java b/rskj-core/src/main/java/org/ethereum/vm/program/Program.java index 6eb1f2f67b2..1d28804eb75 100644 --- a/rskj-core/src/main/java/org/ethereum/vm/program/Program.java +++ b/rskj-core/src/main/java/org/ethereum/vm/program/Program.java @@ -95,7 +95,6 @@ public class Program { private static final Logger logger = LoggerFactory.getLogger("VM"); private static final Logger gasLogger = LoggerFactory.getLogger("gas"); - public static final long MAX_MEMORY = (1<<30); //Max size for stack checks @@ -1000,6 +999,10 @@ private void storageSave(byte[] key, byte[] val) { getStorage().addStorageRow(getOwnerRskAddress(), keyWord, valWord); } + public void transientStorageSave(DataWord key, DataWord value) { + getStorage().addTransientStorageRow(getOwnerRskAddress(), key, value); + } + private RskAddress getOwnerRskAddress() { if (rskOwnerAddress == null) { rskOwnerAddress = new RskAddress(getOwnerAddress()); @@ -1110,6 +1113,10 @@ public DataWord storageLoad(DataWord key) { return getStorage().getStorageValue(getOwnerRskAddress(), key); } + public DataWord transientStorageLoad(DataWord key) { + return getStorage().getTransientStorageValue(getOwnerRskAddress(), key); + } + public DataWord getPrevHash() { return invoke.getPrevHash(); } diff --git a/rskj-core/src/main/java/org/ethereum/vm/program/Storage.java b/rskj-core/src/main/java/org/ethereum/vm/program/Storage.java index 836e4d4122a..99802802b9b 100644 --- a/rskj-core/src/main/java/org/ethereum/vm/program/Storage.java +++ b/rskj-core/src/main/java/org/ethereum/vm/program/Storage.java @@ -30,6 +30,7 @@ import org.ethereum.vm.program.listener.ProgramListener; import org.ethereum.vm.program.listener.ProgramListenerAware; +import javax.annotation.Nullable; import java.math.BigInteger; import java.util.Iterator; import java.util.Set; @@ -223,4 +224,31 @@ public byte[] getRoot() { public void updateAccountState(RskAddress addr, AccountState accountState) { throw new UnsupportedOperationException(); } + + @Override + public void addTransientStorageRow(RskAddress addr, DataWord key, DataWord value) { + repository.addTransientStorageRow(addr, key, value); + } + + @Override + public void addTransientStorageBytes(RskAddress addr, DataWord key, byte[] value) { + repository.addTransientStorageBytes(addr, key, value); + } + + @Override + public void clearTransientStorage() { + repository.clearTransientStorage(); + } + + @Nullable + @Override + public DataWord getTransientStorageValue(RskAddress addr, DataWord key) { + return repository.getTransientStorageValue(addr, key); + } + + @Nullable + @Override + public byte[] getTransientStorageBytes(RskAddress addr, DataWord key) { + return repository.getTransientStorageBytes(addr, key); + } } diff --git a/rskj-core/src/main/resources/expected.conf b/rskj-core/src/main/resources/expected.conf index 7a9dd67ca53..21d2159e71c 100644 --- a/rskj-core/src/main/resources/expected.conf +++ b/rskj-core/src/main/resources/expected.conf @@ -20,90 +20,91 @@ blockchain = { lovell700 = } consensusRules = { - areBridgeTxsPaid = - rskip85 = - rskip87 = - rskip88 = - rskip89 = - rskip90 = - rskip91 = - rskip92 = - rskip97 = - rskip98 = - rskip103 = - rskip106 = - rskip110 = - rskip119 = - rskip120 = - rskip122 = - rskip123 = - rskip124 = - rskip125 = - rskip126 = - rskip132 = - rskip134 = - rskip136 = - rskip137 = - rskip140 = - rskip143 = - rskip146 = - rskip150 = - rskip151 = - rskip152 = - rskip156 = - rskipUMM = - rskip153 = - rskip169 = - rskip170 = - rskip171 = - rskip174 = - rskip176 = - rskip179 = - rskip180 = - rskip181 = - rskip185 = - rskip186 = - rskip191 = - rskip197 = - rskip199 = - rskip200 = - rskip201 = - rskip203 = - rskip218 = - rskip219 = - rskip220 = - rskip252 = - rskip271 = - rskip284 = - rskip290 = - rskip293 = - rskip294 = - rskip297 = - rskip351 = - rskip144 = - rskip326 = - rskip353 = - rskip357 = - rskip374 = - rskip375 = - rskip376 = - rskip377 = - rskip379 = - rskip383 = - rskip385 = - rskip398 = - rskip400 = - rskip412 = - rskip415 = - rskip417 = - rskip427 = - rskip428 = - rskip434 = - rskip438 = - rskip445 = - rskip453 = - rskip454 = - } + areBridgeTxsPaid = + rskip85 = + rskip87 = + rskip88 = + rskip89 = + rskip90 = + rskip91 = + rskip92 = + rskip97 = + rskip98 = + rskip103 = + rskip106 = + rskip110 = + rskip119 = + rskip120 = + rskip122 = + rskip123 = + rskip124 = + rskip125 = + rskip126 = + rskip132 = + rskip134 = + rskip136 = + rskip137 = + rskip140 = + rskip143 = + rskip146 = + rskip150 = + rskip151 = + rskip152 = + rskip156 = + rskipUMM = + rskip153 = + rskip169 = + rskip170 = + rskip171 = + rskip174 = + rskip176 = + rskip179 = + rskip180 = + rskip181 = + rskip185 = + rskip186 = + rskip191 = + rskip197 = + rskip199 = + rskip200 = + rskip201 = + rskip203 = + rskip218 = + rskip219 = + rskip220 = + rskip252 = + rskip271 = + rskip284 = + rskip290 = + rskip293 = + rskip294 = + rskip297 = + rskip351 = + rskip144 = + rskip326 = + rskip353 = + rskip357 = + rskip374 = + rskip375 = + rskip376 = + rskip377 = + rskip379 = + rskip383 = + rskip385 = + rskip398 = + rskip400 = + rskip412 = + rskip415 = + rskip417 = + rskip427 = + rskip428 = + rskip434 = + rskip438 = + rskip445 = + rskip446 = + rskip453 = + rskip454 = + } } gc = { enabled = diff --git a/rskj-core/src/main/resources/reference.conf b/rskj-core/src/main/resources/reference.conf index fe492c435c8..d35f0988b72 100644 --- a/rskj-core/src/main/resources/reference.conf +++ b/rskj-core/src/main/resources/reference.conf @@ -86,6 +86,7 @@ blockchain = { rskip434 = arrowhead631 rskip438 = lovell700 rskip445 = lovell700 + rskip446 = lovell700 rskip453 = lovell700 rskip454 = lovell700 } diff --git a/rskj-core/src/test/java/co/rsk/vm/opcode/TransientStorageDslTest.java b/rskj-core/src/test/java/co/rsk/vm/opcode/TransientStorageDslTest.java new file mode 100644 index 00000000000..9bff2017b6b --- /dev/null +++ b/rskj-core/src/test/java/co/rsk/vm/opcode/TransientStorageDslTest.java @@ -0,0 +1,620 @@ +/* + * This file is part of RskJ + * Copyright (C) 2024 RSK Labs Ltd. + * (derived from ethereumJ library, Copyright (c) 2016 ) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package co.rsk.vm.opcode; + +import co.rsk.config.TestSystemProperties; +import co.rsk.test.World; +import co.rsk.test.dsl.DslParser; +import co.rsk.test.dsl.DslProcessorException; +import co.rsk.test.dsl.WorldDslProcessor; +import com.typesafe.config.ConfigValueFactory; +import org.ethereum.core.Block; +import org.ethereum.core.Transaction; +import org.ethereum.core.TransactionReceipt; +import org.ethereum.core.util.TransactionReceiptUtil; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.FileNotFoundException; +import java.math.BigInteger; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class TransientStorageDslTest { + + @Test + void testTransientStorageOpcodesExecutionsWithRSKIPActivated() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/tload_tstore_basic_tests.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String mainContractTransientStorageCreationTxName = "txTestTransientStorageContract"; + assertTransactionReceiptWithStatus(world, mainContractTransientStorageCreationTxName, "b01", true); + + String secondaryContractTransientStorageCreationTxName = "txTestTransientStorageOtherContract"; + assertTransactionReceiptWithStatus(world, secondaryContractTransientStorageCreationTxName, "b02", true); + + String checkingOpcodesTxName = "txTestTransientStorageOpCodes"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, checkingOpcodesTxName, "b03", true); + Assertions.assertEquals(1, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String checkingOpcodesTxName2 = "txTestTransientStorageOpCodesOtherValue"; + TransactionReceipt txReceipt2 = assertTransactionReceiptWithStatus(world, checkingOpcodesTxName2, "b04", true); + Assertions.assertEquals(1, TransactionReceiptUtil.getEventCount(txReceipt2, "OK", null)); + } + + @Test + void testTransientStorageOpcodesShareMemorySameTransaction() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/tload_tstore_basic_tests.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String mainContractTransientStorageCreationTxName = "txTestTransientStorageContract"; + assertTransactionReceiptWithStatus(world, mainContractTransientStorageCreationTxName, "b01", true); + + String secondaryContractTransientStorageCreationTxName = "txTestTransientStorageOtherContract"; + assertTransactionReceiptWithStatus(world, secondaryContractTransientStorageCreationTxName, "b02", true); + + String checkingOpcodesTxName = "txTestTransientStorageNestedTransactionShareMemory"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, checkingOpcodesTxName, "b05", true); + Assertions.assertEquals(1, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testTransientStorageOpcodesDoesntShareMemoryFromOtherContract() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/tload_tstore_basic_tests.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String mainContractTransientStorageCreationTxName = "txTestTransientStorageContract"; + assertTransactionReceiptWithStatus(world, mainContractTransientStorageCreationTxName, "b01", true); + + String secondaryContractTransientStorageCreationTxName = "txTestTransientStorageOtherContract"; + assertTransactionReceiptWithStatus(world, secondaryContractTransientStorageCreationTxName, "b02", true); + + String checkingOpcodesTxName = "txTestTransientStorageNestedTransactionOtherContractDoesntShareMemory"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, checkingOpcodesTxName, "b06", true); + Assertions.assertEquals(1, TransactionReceiptUtil.getEventCount(txReceipt, "ERROR", new String[]{"bytes32"})); + } + + @Test + void testTransientStorageOpcodesExecutionFailsWithRSKIPDeactivated() throws FileNotFoundException, DslProcessorException { + TestSystemProperties rskip446Disabled = new TestSystemProperties(rawConfig -> + rawConfig.withValue("blockchain.config.hardforkActivationHeights.lovell700", ConfigValueFactory.fromAnyRef(-1)) + ); + + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/tload_tstore_basic_tests.txt"); + World world = new World(rskip446Disabled); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String mainContractTransientStorageCreationTxName = "txTestTransientStorageContract"; + assertTransactionReceiptWithStatus(world, mainContractTransientStorageCreationTxName, "b01", true); + + String secondaryContractTransientStorageCreationTxName = "txTestTransientStorageOtherContract"; + assertTransactionReceiptWithStatus(world, secondaryContractTransientStorageCreationTxName, "b02", true); + + String checkingOpcodesTxName = "txTestTransientStorageOpCodes"; + assertTransactionReceiptWithStatus(world, checkingOpcodesTxName, "b03", false); + } + + @Test + void testTransientStorageTestsEip1153BasicScenarios() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/eip1153_basic_tests.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String mainContractTransientStorageCreationTxName = "txTestTransientStorageContract"; + assertTransactionReceiptWithStatus(world, mainContractTransientStorageCreationTxName, "b01", true); + + String txTestTloadAfterSstore = "txTestTloadAfterSstore"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txTestTloadAfterSstore, "b02", true); + Assertions.assertEquals(4, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txTestTloadAfterTstore = "txTestTloadAfterTstore"; + txReceipt = assertTransactionReceiptWithStatus(world, txTestTloadAfterTstore, "b03", true); + Assertions.assertEquals(4, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txTestTransientUnsetValues = "txTestTransientUnsetValues"; + txReceipt = assertTransactionReceiptWithStatus(world, txTestTransientUnsetValues, "b04", true); + Assertions.assertEquals(4, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txTestTloadAfterTstoreIsZero = "txTestTloadAfterTstoreIsZero"; + txReceipt = assertTransactionReceiptWithStatus(world, txTestTloadAfterTstoreIsZero, "b04", true); + Assertions.assertEquals(4, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testOnlyConstructorCodeCreateContext() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/only_constructor_code_create_context.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTestTransientStorageCreateContextsContract = "txTestTransientStorageCreateContextsContract"; + assertTransactionReceiptWithStatus(world, txTestTransientStorageCreateContextsContract, "b01", true); + + String txOnlyConstructorCode = "txOnlyConstructorCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txOnlyConstructorCode, "b02", true); + Assertions.assertEquals(5, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testInConstructorAndCodeCreateContext() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/in_constructor_and_deploy_code_create_context.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTestTransientStorageCreateContextsContract = "txTestTransientStorageCreateContextsContract"; + assertTransactionReceiptWithStatus(world, txTestTransientStorageCreateContextsContract, "b01", true, 2); + + String txInConstructorAndCode = "txInConstructorAndCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txInConstructorAndCode, "b01", true, 2); + Assertions.assertEquals(6, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testAccrossConstructorAndCodeV0CreateContext() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/accross_constructor_and_deploy_code_v0_create_context.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTestTransientStorageCreateContextsContract = "txTestTransientStorageCreateContextsContract"; + assertTransactionReceiptWithStatus(world, txTestTransientStorageCreateContextsContract, "b01", true, 2); + + String txAcrossConstructorAndCodeV0 = "txAcrossConstructorAndCodeV0"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txAcrossConstructorAndCodeV0, "b01", true, 2); + Assertions.assertEquals(6, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testAccrossConstructorAndCodeV1CreateContext() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/accross_constructor_and_deploy_code_v1_create_context.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTestTransientStorageCreateContextsContract = "txTestTransientStorageCreateContextsContract"; + assertTransactionReceiptWithStatus(world, txTestTransientStorageCreateContextsContract, "b01", true); + + String txAcrossConstructorAndCodeV1 = "txAcrossConstructorAndCodeV1"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txAcrossConstructorAndCodeV1, "b02", true); + Assertions.assertEquals(7, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testNoConstructorCodeCreateContext() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/no_constructor_code_create_context.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTestTransientStorageCreateContextsContract = "txTestTransientStorageCreateContextsContract"; + assertTransactionReceiptWithStatus(world, txTestTransientStorageCreateContextsContract, "b01", true); + + String txNoConstructorCode = "txNoConstructorCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txNoConstructorCode, "b02", true); + Assertions.assertEquals(5, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testDynamicExecutionContextSimpleScenario() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/dynamic_execution_context_simple.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txCallAndDelegateCallSimpleTest = "txCallAndDelegateCallSimpleTest"; + assertTransactionReceiptWithStatus(world, txCallAndDelegateCallSimpleTest, "b01", true); + + String txExecuteCallCode = "txExecuteCallCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCallCode, "b02", true,2); + Assertions.assertEquals(5, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteDelegateCall = "txExecuteDelegateCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteDelegateCall, "b02", true, 2); + Assertions.assertEquals(5, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testDynamicExecutionContextWithRevert() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/dynamic_execution_context_with_revert.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txDynamicExecutionContextWithRevertTest = "txDynamicExecutionContextWithRevertTest"; + assertTransactionReceiptWithStatus(world, txDynamicExecutionContextWithRevertTest, "b01", true); + + String txExecuteCallCode = "txExecuteCallCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCallCode, "b02", true, 3); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteDelegateCall = "txExecuteDelegateCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteDelegateCall, "b02", true, 3); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteCall = "txExecuteCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCall, "b02", true, 3); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testDynamicExecutionContextWithInvalid() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/dynamic_execution_context_with_invalid.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txDynamicExecutionContextWithInvalidTest = "txDynamicExecutionContextWithInvalidTest"; + assertTransactionReceiptWithStatus(world, txDynamicExecutionContextWithInvalidTest, "b01", true); + + String txExecuteCallCode = "txExecuteCallCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCallCode, "b02", true, 3); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteDelegateCall = "txExecuteDelegateCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteDelegateCall, "b02", true, 3); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteCall = "txExecuteCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCall, "b02", true, 3); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testDynamicExecutionContextWithStackOverflow() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/dynamic_execution_context_with_stack_overflow.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txDynamicExecutionContextWithStackOverflowTest = "txDynamicExecutionContextWithStackOverflowTest"; + assertTransactionReceiptWithStatus(world, txDynamicExecutionContextWithStackOverflowTest, "b01", true); + + String txExecuteCallCode = "txExecuteCallCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCallCode, "b02", true,3); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteDelegateCall = "txExecuteDelegateCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteDelegateCall, "b02", true, 3); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txExecuteCall = "txExecuteCall"; + txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCall, "b02", true, 3); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testDynamicExecutionCallContextSubcall() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/dynamic_execution_context_call_subcall.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txContextCallSubcallContract = "txContextCallSubcallContract"; + assertTransactionReceiptWithStatus(world, txContextCallSubcallContract, "b01", true); + + String txExecuteCallCode = "txExecuteCallCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteCallCode, "b02", true); + Assertions.assertEquals(6, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testDynamicExecutionStaticCallSubcallCantUseTstore() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/dynamic_execution_context_staticcall_subcall_cant_call_tstore.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txContextStaticCallCantCallTstoreContract = "txContextStaticCallCantCallTstoreContract"; + assertTransactionReceiptWithStatus(world, txContextStaticCallCantCallTstoreContract, "b01", true); + + String txExecuteStaticCallCode = "txExecuteStaticCallCode"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txExecuteStaticCallCode, "b02", true); + Assertions.assertEquals(2, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testDynamicReentrancyContextsTstoreBeforeRevertOrInvalidHasNoEffect() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/dynamic_reentrancy_context_tstore_before_revert_or_invalid_has_no_effect.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTstorageDynamicReentrancyContextContract = "txTstorageDynamicReentrancyContextContract"; + assertTransactionReceiptWithStatus(world, txTstorageDynamicReentrancyContextContract, "b01", true, 3); + + String txTestReentrantContextRevert = "txTestReentrantContextRevert"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txTestReentrantContextRevert, "b01", true, 3); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txTestReentrantContextInvalid = "txTestReentrantContextInvalid"; + assertTransactionReceiptWithStatus(world, txTestReentrantContextInvalid, "b01", false, 3); + } + + @Test + void testDynamicReentrancyContextsRevertOrInvalidUndoesAll() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/dynamic_reentrancy_context_revert_or_invalid_undoes_all.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTstorageDynamicReentrancyContextContract = "txTstorageDynamicReentrancyContextContract"; + assertTransactionReceiptWithStatus(world, txTstorageDynamicReentrancyContextContract, "b01", true); + + String txTestReentrantContextRevert = "txTestReentrantContextRevert"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txTestReentrantContextRevert, "b02", true); + Assertions.assertEquals(5, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txTestReentrantContextInvalid = "txTestReentrantContextInvalid"; + assertTransactionReceiptWithStatus(world, txTestReentrantContextInvalid, "b03", false); + } + + @Test + void testDynamicReentrancyContextsRevertOrInvalidUndoesTstorageAfterSuccessfullCall() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/dynamic_reentrancy_context_revert_or_invalid_undoes_tstorage_after_successfull_call.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTstorageDynamicReentrancyContextContract = "txTstorageDynamicReentrancyContextContract"; + assertTransactionReceiptWithStatus(world, txTstorageDynamicReentrancyContextContract, "b01", true); + + String txTstoreInDoubleReentrantCallWithRevert = "txTstoreInDoubleReentrantCallWithRevert"; + assertTransactionReceiptWithStatus(world, txTstoreInDoubleReentrantCallWithRevert, "b02", true); + + String txCheckValuesStoredInTstorageForRevert = "txCheckValuesStoredInTstorageForRevert"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txCheckValuesStoredInTstorageForRevert, "b03", true); + Assertions.assertEquals(4, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + + String txTstoreInDoubleReentrantCallWithInvalid = "txTstoreInDoubleReentrantCallWithInvalid"; + assertTransactionReceiptWithStatus(world, txTstoreInDoubleReentrantCallWithInvalid, "b04", false); + + String txCheckValuesStoredInTstorageForInvalid = "txCheckValuesStoredInTstorageForInvalid"; + txReceipt = assertTransactionReceiptWithStatus(world, txCheckValuesStoredInTstorageForInvalid, "b05", true); + Assertions.assertEquals(4, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testReentrancyContextsTstoreAfterReentrantCall() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/reentrancy_context_tstore_after_reentrant_call.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTstorageReentrancyContextTestContract = "txTstorageReentrancyContextTestContract"; + assertTransactionReceiptWithStatus(world, txTstorageReentrancyContextTestContract, "b01", true, 3); + + String txTstoreInReentrantCall = "txTstoreInReentrantCall"; + assertTransactionReceiptWithStatus(world, txTstoreInReentrantCall, "b01", true, 3); + + String txCheckValuesStoredInTstorage = "txCheckValuesStoredInTstorage"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txCheckValuesStoredInTstorage, "b01", true, 3); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testReentrancyContextsTloadAfterReentrantTstore() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/reentrancy_context_tload_after_reentrant_tstore.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTstorageReentrancyContextTestContract = "txTstorageReentrancyContextTestContract"; + assertTransactionReceiptWithStatus(world, txTstorageReentrancyContextTestContract, "b01", true); + + String txTloadAfterReentrantTstore = "txTloadAfterReentrantTstore"; + assertTransactionReceiptWithStatus(world, txTloadAfterReentrantTstore, "b02", true); + + String txCheckValuesStoredInTstorage = "txCheckValuesStoredInTstorage"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txCheckValuesStoredInTstorage, "b03", true); + Assertions.assertEquals(3, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testReentrancyContextsManipulateInReentrantCall() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/reentrancy_context_manipulate_in_reentrant_call.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTstorageReentrancyContextTestContract = "txTstorageReentrancyContextTestContract"; + assertTransactionReceiptWithStatus(world, txTstorageReentrancyContextTestContract, "b01", true); + + String txManipulateInReentrantCall = "txManipulateInReentrantCall"; + assertTransactionReceiptWithStatus(world, txManipulateInReentrantCall, "b02", true); + + String txCheckValuesStoredInTstorage = "txCheckValuesStoredInTstorage"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txCheckValuesStoredInTstorage, "b03", true); + Assertions.assertEquals(4, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testReentrancyContextsTstoreInCallThenTloadReturnInStaticCall() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/reentrancy_context_tstore_in_call_then_tload_return_in_static_call.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTstorageReentrancyContextTestContract = "txTstorageReentrancyContextTestContract"; + assertTransactionReceiptWithStatus(world, txTstorageReentrancyContextTestContract, "b01", true); + + String txTstorageInReentrantCallTest = "txTstorageInReentrantCallTest"; + assertTransactionReceiptWithStatus(world, txTstorageInReentrantCallTest, "b02", true); + + String txCheckValuesStoredInTstorage = "txCheckValuesStoredInTstorage"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txCheckValuesStoredInTstorage, "b03", true); + Assertions.assertEquals(5, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testTransientStorageGasMeasureTests() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/tstorage_gas_measure_tests.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTstorageGasMeasureTestContract = "txTstorageGasMeasureTestContract"; + assertTransactionReceiptWithStatus(world, txTstorageGasMeasureTestContract, "b01", true); + + String txCheckGasMeasures = "txCheckGasMeasures"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txCheckGasMeasures, "b02", true); + Assertions.assertEquals(4, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + @Test + void testTstoreLoopUntilOutOfGas() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/tstore_loop_until_out_of_gas.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTstoreLoopUntilOutOfGasContract = "txTstoreLoopUntilOutOfGasContract"; + assertTransactionReceiptWithStatus(world, txTstoreLoopUntilOutOfGasContract, "b01", true); + + String txRunTstoreUntilOutOfGas = "txRunTstoreUntilOutOfGas"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txRunTstoreUntilOutOfGas, "b02", false); + long txRunOutOfGas = new BigInteger(1, txReceipt.getGasUsed()).longValue(); + assertEquals(300000, txRunOutOfGas); // Assert that it consumed all the gas configured in the transaction + } + + @Test + void testTstoreWideAddressSpaceLoopUntilOutOfGas() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/tstore_wide_address_space_loop_until_out_of_gas.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTstoreWideAddressSpaceLoopUntilOutOfGasContract = "txTstoreWideAddressSpaceLoopUntilOutOfGasContract"; + assertTransactionReceiptWithStatus(world, txTstoreWideAddressSpaceLoopUntilOutOfGasContract, "b01", true); + + String txRunTstoreWideAddressSpaceUntilOutOfGas = "txRunTstoreWideAddressSpaceUntilOutOfGas"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txRunTstoreWideAddressSpaceUntilOutOfGas, "b02", false); + long txRunOutOfGas = new BigInteger(1, txReceipt.getGasUsed()).longValue(); + assertEquals(500000, txRunOutOfGas); // Assert that it consumed all the gas configured in the transaction + } + + @Test + void testTstoreAndTloadLoopUntilOutOfGas() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/tstore_and_tload_loop_until_out_of_gas.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTstoreAndTloadLoopUntilOutOfGasContract = "txTstoreAndTloadLoopUntilOutOfGasContract"; + assertTransactionReceiptWithStatus(world, txTstoreAndTloadLoopUntilOutOfGasContract, "b01", true); + + String txRunTstoreAndTloadUntilOutOfGas = "txRunTstoreAndTloadUntilOutOfGas"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txRunTstoreAndTloadUntilOutOfGas, "b02", false); + long txRunOutOfGas = new BigInteger(1, txReceipt.getGasUsed()).longValue(); + assertEquals(700000, txRunOutOfGas); // Assert that it consumed all the gas configured in the transaction + } + + @ParameterizedTest + @MethodSource("provideParametersForSelfDestructCases") + void testTstorageSelfDestructCases_OnEachTest_TheEventsEmittedAreTheExpected(String dslFile, Integer numberOfOksEmitted) throws FileNotFoundException, DslProcessorException { + + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/" + dslFile); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txDeployTestContract = "txDeployTestContract"; + assertTransactionReceiptWithStatus(world, txDeployTestContract, "b01", true); + + String txCheckValuesStoredInTstorage = "txPerformTest"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txCheckValuesStoredInTstorage, "b02", true); + Assertions.assertEquals(numberOfOksEmitted, TransactionReceiptUtil.getEventCount(txReceipt, "OK", null)); + } + + private static Stream provideParametersForSelfDestructCases() { + return Stream.of( + Arguments.of("tload_after_selfdestruct_pre_existing_contract.txt", 3 ), + Arguments.of("tload_after_selfdestruct_new_contract.txt", 3 ), + Arguments.of("tload_after_inner_selfdestruct_pre_existing_contract.txt", 2 ), + Arguments.of("tload_after_inner_selfdestruct_new_contract.txt", 2 ), + Arguments.of("tstore_after_selfdestruct_pre_existing_contract.txt", 4 ), + Arguments.of("tstore_after_selfdestruct_new_contract.txt", 4 ) + ); + } + + @Test + void testTloadTstoreCheckingBetweenTransactions() throws FileNotFoundException, DslProcessorException { + DslParser parser = DslParser.fromResource("dsl/transient_storage_rskip446/tload_tstore_checking_between_transactions.txt"); + World world = new World(); + WorldDslProcessor processor = new WorldDslProcessor(world); + processor.processCommands(parser); + + String txTloadTstoreCheckingBetweenTransactionsContract = "txTloadTstoreCheckingBetweenTransactionsContract"; + assertTransactionReceiptWithStatus(world, txTloadTstoreCheckingBetweenTransactionsContract, "b01", true); + + String txTstoreAndTloadSomeValue = "txTstoreAndTloadSomeValue"; + TransactionReceipt txReceipt = assertTransactionReceiptWithStatus(world, txTstoreAndTloadSomeValue, "b02", true, 2); + + Assertions.assertEquals(1, TransactionReceiptUtil.getEventCount(txReceipt, "ValueStored", new String[]{"uint256","uint256"})); + Assertions.assertEquals(1, TransactionReceiptUtil.getEventCount(txReceipt, "ValueLoaded", new String[]{"uint256","uint256"})); + + String txTloadSomeValueAndCheckWithExpected = "txTloadSomeValueAndCheckWithExpected"; + TransactionReceipt txReceipt2 = assertTransactionReceiptWithStatus(world, txTloadSomeValueAndCheckWithExpected, "b02", true, 2); + + Assertions.assertEquals(1, TransactionReceiptUtil.getEventCount(txReceipt2, "ValueLoaded", new String[]{"uint256","uint256"})); + Assertions.assertEquals(1, TransactionReceiptUtil.getEventCount(txReceipt2, "OK", null)); + } + + private static TransactionReceipt assertTransactionReceiptWithStatus(World world, String txName, String blockName, boolean withSuccess) { + return assertTransactionReceiptWithStatus(world, txName, blockName, withSuccess, 1); + } + + private static TransactionReceipt assertTransactionReceiptWithStatus(World world, String txName, String blockName, boolean withSuccess, int numberOfTransactionsInBlock) { + Transaction txCreation = world.getTransactionByName(txName); + assertNotNull(txCreation); + + Block block = world.getBlockByName(blockName); + assertEquals(numberOfTransactionsInBlock, block.getTransactionsList().size()); + + TransactionReceipt txReceipt = world.getTransactionReceiptByName(txName); + assertNotNull(txReceipt); + + byte[] status = txReceipt.getStatus(); + assertNotNull(status); + + if(withSuccess) { + assertTrue(txReceipt.isSuccessful()); + } else { + assertFalse(txReceipt.isSuccessful()); + } + return txReceipt; + } + +} diff --git a/rskj-core/src/test/java/co/rsk/vm/opcode/TransientStorageTest.java b/rskj-core/src/test/java/co/rsk/vm/opcode/TransientStorageTest.java new file mode 100644 index 00000000000..a033b4e1901 --- /dev/null +++ b/rskj-core/src/test/java/co/rsk/vm/opcode/TransientStorageTest.java @@ -0,0 +1,151 @@ +/* + * This file is part of RskJ + * Copyright (C) 2024 RSK Labs Ltd. + * (derived from ethereumJ library, Copyright (c) 2016 ) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package co.rsk.vm.opcode; + +import co.rsk.config.TestSystemProperties; +import co.rsk.config.VmConfig; +import co.rsk.vm.BytecodeCompiler; +import org.ethereum.config.blockchain.upgrades.ActivationConfig; +import org.ethereum.core.BlockFactory; +import org.ethereum.core.BlockTxSignatureCache; +import org.ethereum.core.ReceivedTxSignatureCache; +import org.ethereum.vm.DataWord; +import org.ethereum.vm.PrecompiledContracts; +import org.ethereum.vm.VM; +import org.ethereum.vm.program.Program; +import org.ethereum.vm.program.Stack; +import org.ethereum.vm.program.invoke.ProgramInvokeMockImpl; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.HashSet; + +import static org.ethereum.config.blockchain.upgrades.ConsensusRule.RSKIP446; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class TransientStorageTest { + private final TestSystemProperties config = new TestSystemProperties(); + private final BlockFactory blockFactory = new BlockFactory(config.getActivationConfig()); + private final PrecompiledContracts precompiledContracts = new PrecompiledContracts(config, null, new BlockTxSignatureCache(new ReceivedTxSignatureCache())); + private VmConfig vmConfig = config.getVmConfig(); + private ProgramInvokeMockImpl invoke; + private BytecodeCompiler compiler; + + @BeforeEach + void setup() { + invoke = new ProgramInvokeMockImpl(); + compiler = new BytecodeCompiler(); + } + + @Test + void testTLoadDynamicExecutionContextUnderflow(){ + //given + ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class); + when(activations.isActive(RSKIP446)).thenReturn(true); + + //when-then + Assertions.assertThrows(Program.StackTooSmallException.class, () -> executeCodeWithActivationConfig("TLOAD", 2, activations)); + } + + @Test + void testTLoadDynamicExecutionContextWorksFine(){ + //given + ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class); + when(activations.isActive(RSKIP446)).thenReturn(true); + String expected = "0000000000000000000000000000000000000000000000000000000000000000"; + + //when + Program program = executeCodeWithActivationConfig("PUSH32 0x0000000000000000000000000000000000000000000000000000000000000001 TLOAD", 2, activations); + Stack stack = program.getStack(); + + //then + assertEquals(1, stack.size()); + assertEquals(DataWord.valueFromHex(expected), stack.peek()); + } + + + @Test + void testTStoreDynamicExecutionContextUnderflow(){ + //given + ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class); + when(activations.isActive(RSKIP446)).thenReturn(true); + + //when-then + Assertions.assertThrows(Program.StackTooSmallException.class, () -> executeCodeWithActivationConfig("TSTORE", 3, activations)); + } + + + @Test + void testTStoreDynamicExecutionContextWorksFine(){ + //given + ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class); + when(activations.isActive(RSKIP446)).thenReturn(true); + String expected = "0000000000000000000000000000000000000000000000000000000000000000"; + + //when + Program program = executeCodeWithActivationConfig("PUSH32 0x0000000000000000000000000000000000000000000000000000000000000420 " + + "PUSH32 0x0000000000000000000000000000000000000000000000000000000000000001 " + + "TSTORE", 3, activations); + Stack stack = program.getStack(); + + //then + assertEquals(0, stack.size()); + assertNull(program.getResult().getException()); + } + + @Test + void testTStoreTloadDynamicExecutionContextWorksFine(){ + //given + ActivationConfig.ForBlock activations = mock(ActivationConfig.ForBlock.class); + when(activations.isActive(RSKIP446)).thenReturn(true); + String expected = "0000000000000000000000000000000000000000000000000000000000000420"; + + //when + Program program = executeCodeWithActivationConfig("PUSH32 0x0000000000000000000000000000000000000000000000000000000000000420 " + + "PUSH32 0x0000000000000000000000000000000000000000000000000000000000000001 " + + "TSTORE " + + "PUSH32 0x0000000000000000000000000000000000000000000000000000000000000001 " + + "TLOAD ", 5, activations); + Stack stack = program.getStack(); + + //then + assertEquals(1, stack.size()); + assertEquals(DataWord.valueFromHex(expected), stack.peek()); + } + + + private Program executeCodeWithActivationConfig(String code, int nsteps, ActivationConfig.ForBlock activations) { + return executeCodeWithActivationConfig(compiler.compile(code), nsteps, activations); + } + private Program executeCodeWithActivationConfig(byte[] code, int nsteps, ActivationConfig.ForBlock activations) { + VM vm = new VM(vmConfig, precompiledContracts); + Program program = new Program(vmConfig, precompiledContracts, blockFactory, activations, code, invoke,null, new HashSet<>(), new BlockTxSignatureCache(new ReceivedTxSignatureCache())); + + for (int k = 0; k < nsteps; k++) { + vm.step(program); + } + + return program; + } +} diff --git a/rskj-core/src/test/java/org/ethereum/config/blockchain/upgrades/ActivationConfigTest.java b/rskj-core/src/test/java/org/ethereum/config/blockchain/upgrades/ActivationConfigTest.java index 3700d7279f5..b90d7f849ec 100644 --- a/rskj-core/src/test/java/org/ethereum/config/blockchain/upgrades/ActivationConfigTest.java +++ b/rskj-core/src/test/java/org/ethereum/config/blockchain/upgrades/ActivationConfigTest.java @@ -127,6 +127,7 @@ class ActivationConfigTest { " rskip434: arrowhead631", " rskip438: lovell700", " rskip445: lovell700", + " rskip446: lovell700", " rskip453: lovell700", " rskip454: lovell700", "}" diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/accross_constructor_and_deploy_code_v0_create_context.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/accross_constructor_and_deploy_code_v0_create_context.txt new file mode 100644 index 00000000000..d7be1e8d157 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/accross_constructor_and_deploy_code_v0_create_context.txt @@ -0,0 +1,129 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; +contract AcrossConstructorAndCodeV0 { + constructor() { + assembly{ + tstore(1, 0x0000000000000000000000000000000000000000000000000000000000000111) + } + } + + event OK(); + event ERROR(string, bytes32); + + function deployedCode() external { + bytes32 valueLoadedInitially; + bytes32 valueLoadedAfterStore; + bytes32 valueLoadedAfterStore2; + + assembly{ + valueLoadedInitially := tload(0) + valueLoadedAfterStore := tload(1) + + tstore(2, 0x0000000000000000000000000000000000000000000000000000000000000222) + valueLoadedAfterStore2 := tload(2) + } + checkReturnValueExpected(valueLoadedInitially, 'Checking value loaded in 0 from creator is inacessible', 0x00); + checkReturnValueExpected(valueLoadedAfterStore, 'Checking value stored in 1 from constructor is accesible', 0x0000000000000000000000000000000000000000000000000000000000000111); + checkReturnValueExpected(valueLoadedAfterStore2, 'Checking value stored in 2 from deployed code is accesible', 0x0000000000000000000000000000000000000000000000000000000000000222); + } + + function checkReturnValueExpected(bytes32 valueReceived, string memory message, bytes32 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract TestStorageCreateContexts { + constructor(){ + } + + event OK(); + event ERROR(string, bytes32); + + function testAcrossConstructorAndCodeV0() external { + configureTransientStorageFromCaller(); + AcrossConstructorAndCodeV0 testContract = new AcrossConstructorAndCodeV0(); + testContract.deployedCode(); + checkTransientStorageFromCaller(); + } + + function configureTransientStorageFromCaller() private { + assembly{ + tstore(0, 0x0000000000000000000000000000000000000000000000000000000000000002) + tstore(1, 0x0000000000000000000000000000000000000000000000000000000000000003) + tstore(2, 0x0000000000000000000000000000000000000000000000000000000000000004) + calldatacopy(0, 0, calldatasize()) + } + } + + function checkTransientStorageFromCaller() private { + bytes32 valueIn0Received; + bytes32 valueIn1Received; + bytes32 valueIn2Received; + + assembly{ + valueIn0Received := tload(0) + valueIn1Received := tload(1) + valueIn2Received := tload(2) + } + checkReturnValueExpected(valueIn0Received, 'Checking value in 0', 0x0000000000000000000000000000000000000000000000000000000000000002); + checkReturnValueExpected(valueIn1Received, 'Checking value in 1', 0x0000000000000000000000000000000000000000000000000000000000000003); + checkReturnValueExpected(valueIn2Received, 'Checking value in 2', 0x0000000000000000000000000000000000000000000000000000000000000004); + } + + function checkReturnValueExpected(bytes32 valueReceived, string memory message, bytes32 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TestStorageCreateContexts: 6080604052348015600e575f80fd5b506106248061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063573d900a1461002d575b5f80fd5b610035610037565b005b61003f6100ce565b5f60405161004c90610238565b604051809103905ff080158015610065573d5f803e3d5ffd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663a45449eb6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156100ad575f80fd5b505af11580156100bf573d5f803e3d5ffd5b505050506100cb6100e2565b50565b60025f5d600360015d600460025d365f8037565b5f805f805c925060015c915060025c9050610136836040518060400160405280601381526020017f436865636b696e672076616c756520696e20300000000000000000000000000081525060025f1b6101c1565b610179826040518060400160405280601381526020017f436865636b696e672076616c756520696e20310000000000000000000000000081525060035f1b6101c1565b6101bc816040518060400160405280601381526020017f436865636b696e672076616c756520696e20320000000000000000000000000081525060045f1b6101c1565b505050565b8083036101f9577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610233565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161022a9291906102cd565b60405180910390a15b505050565b6102f3806102fc83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61028782610245565b610291818561024f565b93506102a181856020860161025f565b6102aa8161026d565b840191505092915050565b5f819050919050565b6102c7816102b5565b82525050565b5f6040820190508181035f8301526102e5818561027d565b90506102f460208301846102be565b939250505056fe6080604052348015600e575f80fd5b5061011160015d6102d1806100225f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063a45449eb1461002d575b5f80fd5b610035610037565b005b5f805f805c925060015c915061022260025d60025c90506100738360405180606001604052806036815260200161022e603691395f801b6100c6565b61009a82604051806060016040528060388152602001610264603891396101115f1b6100c6565b6100c1816040518060600160405280603a81526020016101f4603a91396102225f1b6100c6565b505050565b8083036100fe577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610138565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161012f9291906101c5565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61017f8261013d565b6101898185610147565b9350610199818560208601610157565b6101a281610165565b840191505092915050565b5f819050919050565b6101bf816101ad565b82525050565b5f6040820190508181035f8301526101dd8185610175565b90506101ec60208301846101b6565b939250505056fe436865636b696e672076616c75652073746f72656420696e20322066726f6d206465706c6f79656420636f646520697320616363657369626c65436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c65436865636b696e672076616c75652073746f72656420696e20312066726f6d20636f6e7374727563746f7220697320616363657369626c65a26469706673582212209ee2571c29b98956bca0378cdf0ab06bb7e365dd067acd313c71a9295485b99c64736f6c634300081a0033a26469706673582212204abfd877c203d9e5adee353b20835eede1e284ac7e4b6640e27f13a7e025750d64736f6c634300081a0033 + +573d900a: testAcrossConstructorAndCodeV0() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCreateContextsContract contract +transaction_build txTestTransientStorageCreateContextsContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f80fd5b506106248061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063573d900a1461002d575b5f80fd5b610035610037565b005b61003f6100ce565b5f60405161004c90610238565b604051809103905ff080158015610065573d5f803e3d5ffd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663a45449eb6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156100ad575f80fd5b505af11580156100bf573d5f803e3d5ffd5b505050506100cb6100e2565b50565b60025f5d600360015d600460025d365f8037565b5f805f805c925060015c915060025c9050610136836040518060400160405280601381526020017f436865636b696e672076616c756520696e20300000000000000000000000000081525060025f1b6101c1565b610179826040518060400160405280601381526020017f436865636b696e672076616c756520696e20310000000000000000000000000081525060035f1b6101c1565b6101bc816040518060400160405280601381526020017f436865636b696e672076616c756520696e20320000000000000000000000000081525060045f1b6101c1565b505050565b8083036101f9577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610233565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161022a9291906102cd565b60405180910390a15b505050565b6102f3806102fc83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61028782610245565b610291818561024f565b93506102a181856020860161025f565b6102aa8161026d565b840191505092915050565b5f819050919050565b6102c7816102b5565b82525050565b5f6040820190508181035f8301526102e5818561027d565b90506102f460208301846102be565b939250505056fe6080604052348015600e575f80fd5b5061011160015d6102d1806100225f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063a45449eb1461002d575b5f80fd5b610035610037565b005b5f805f805c925060015c915061022260025d60025c90506100738360405180606001604052806036815260200161022e603691395f801b6100c6565b61009a82604051806060016040528060388152602001610264603891396101115f1b6100c6565b6100c1816040518060600160405280603a81526020016101f4603a91396102225f1b6100c6565b505050565b8083036100fe577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610138565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161012f9291906101c5565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61017f8261013d565b6101898185610147565b9350610199818560208601610157565b6101a281610165565b840191505092915050565b5f819050919050565b6101bf816101ad565b82525050565b5f6040820190508181035f8301526101dd8185610175565b90506101ec60208301846101b6565b939250505056fe436865636b696e672076616c75652073746f72656420696e20322066726f6d206465706c6f79656420636f646520697320616363657369626c65436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c65436865636b696e672076616c75652073746f72656420696e20312066726f6d20636f6e7374727563746f7220697320616363657369626c65a26469706673582212209ee2571c29b98956bca0378cdf0ab06bb7e365dd067acd313c71a9295485b99c64736f6c634300081a0033a26469706673582212204abfd877c203d9e5adee353b20835eede1e284ac7e4b6640e27f13a7e025750d64736f6c634300081a0033 + gas 1000000 + build + +# Create transaction to execute txInConstructorAndCode transaction +transaction_build txAcrossConstructorAndCodeV0 + sender acc1 + nonce 1 + contract txTestTransientStorageCreateContextsContract + value 0 + data 573d900a + gas 1000000 + build + +# Create block to hold txAcrossConstructorAndCodeV0 transaction +block_build b01 + parent g00 + transactions txTestTransientStorageCreateContextsContract txAcrossConstructorAndCodeV0 + gasLimit 3000000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/accross_constructor_and_deploy_code_v1_create_context.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/accross_constructor_and_deploy_code_v1_create_context.txt new file mode 100644 index 00000000000..ea98b332054 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/accross_constructor_and_deploy_code_v1_create_context.txt @@ -0,0 +1,146 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract AcrossConstructorAndCodeV1 { + constructor() { + bytes32 valueLoadedInitially; + assembly{ + valueLoadedInitially := tload(0) + tstore(1, 0x0000000000000000000000000000000000000000000000000000000000000333) + } + checkReturnValueExpected(valueLoadedInitially, 'Checking value loaded in 0 from creator is inacessible in constructor', 0x00); + } + + event OK(); + event ERROR(string, bytes32); + + function deployedCode() external { + bytes32 valueLoadedInitially; + bytes32 valueLoadedAfterStore; + bytes32 valueLoadedAfterStore2; + + assembly{ + valueLoadedInitially := tload(0) + valueLoadedAfterStore := tload(1) + + tstore(2, 0x0000000000000000000000000000000000000000000000000000000000000444) + valueLoadedAfterStore2 := tload(2) + } + checkReturnValueExpected(valueLoadedInitially, 'Checking value loaded in 0 from creator is inacessible', 0x00); + checkReturnValueExpected(valueLoadedAfterStore, 'Checking value stored in 1 from constructor is accesible', 0x0000000000000000000000000000000000000000000000000000000000000333); + checkReturnValueExpected(valueLoadedAfterStore2, 'Checking value stored in 2 from deployed code is accesible', 0x0000000000000000000000000000000000000000000000000000000000000444); + } + + function checkReturnValueExpected(bytes32 valueReceived, string memory message, bytes32 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract TestStorageCreateContexts { + constructor(){ + } + + event OK(); + event ERROR(string, bytes32); + + function testAcrossConstructorAndCodeV1() external { + configureTransientStorageFromCaller(); + AcrossConstructorAndCodeV1 testContract = new AcrossConstructorAndCodeV1(); + testContract.deployedCode(); + checkTransientStorageFromCaller(); + } + + function configureTransientStorageFromCaller() private { + assembly{ + tstore(0, 0x0000000000000000000000000000000000000000000000000000000000000002) + tstore(1, 0x0000000000000000000000000000000000000000000000000000000000000003) + tstore(2, 0x0000000000000000000000000000000000000000000000000000000000000004) + calldatacopy(0, 0, calldatasize()) + } + } + + function checkTransientStorageFromCaller() private { + bytes32 valueIn0Received; + bytes32 valueIn1Received; + bytes32 valueIn2Received; + + assembly{ + valueIn0Received := tload(0) + valueIn1Received := tload(1) + valueIn2Received := tload(2) + } + checkReturnValueExpected(valueIn0Received, 'Checking value in 0', 0x0000000000000000000000000000000000000000000000000000000000000002); + checkReturnValueExpected(valueIn1Received, 'Checking value in 1', 0x0000000000000000000000000000000000000000000000000000000000000003); + checkReturnValueExpected(valueIn2Received, 'Checking value in 2', 0x0000000000000000000000000000000000000000000000000000000000000004); + } + + function checkReturnValueExpected(bytes32 valueReceived, string memory message, bytes32 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TestStorageCreateContexts: 6080604052348015600e575f80fd5b506107cd8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80636fc138181461002d575b5f80fd5b610035610037565b005b61003f6100ce565b5f60405161004c90610238565b604051809103905ff080158015610065573d5f803e3d5ffd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663a45449eb6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156100ad575f80fd5b505af11580156100bf573d5f803e3d5ffd5b505050506100cb6100e2565b50565b60025f5d600360015d600460025d365f8037565b5f805f805c925060015c915060025c9050610136836040518060400160405280601381526020017f436865636b696e672076616c756520696e20300000000000000000000000000081525060025f1b6101c1565b610179826040518060400160405280601381526020017f436865636b696e672076616c756520696e20310000000000000000000000000081525060035f1b6101c1565b6101bc816040518060400160405280601381526020017f436865636b696e672076616c756520696e20320000000000000000000000000081525060045f1b6101c1565b505050565b8083036101f9577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610233565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161022a9291906102cd565b60405180910390a15b505050565b61049c806102fc83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61028782610245565b610291818561024f565b93506102a181856020860161025f565b6102aa8161026d565b840191505092915050565b5f819050919050565b6102c7816102b5565b82525050565b5f6040820190508181035f8301526102e5818561027d565b90506102f460208301846102be565b939250505056fe608060405234801561000f575f80fd5b505f805c905061033360015d61004681604051806080016040528060458152602001610457604591395f801b61004c60201b60201c565b50610179565b808303610084577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100be565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd382846040516100b592919061014b565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610105826100c3565b61010f81856100cd565b935061011f8185602086016100dd565b610128816100eb565b840191505092915050565b5f819050919050565b61014581610133565b82525050565b5f6040820190508181035f83015261016381856100fb565b9050610172602083018461013c565b9392505050565b6102d1806101865f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063a45449eb1461002d575b5f80fd5b610035610037565b005b5f805f805c925060015c915061044460025d60025c90506100738360405180606001604052806036815260200161022e603691395f801b6100c6565b61009a82604051806060016040528060388152602001610264603891396103335f1b6100c6565b6100c1816040518060600160405280603a81526020016101f4603a91396104445f1b6100c6565b505050565b8083036100fe577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610138565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161012f9291906101c5565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61017f8261013d565b6101898185610147565b9350610199818560208601610157565b6101a281610165565b840191505092915050565b5f819050919050565b6101bf816101ad565b82525050565b5f6040820190508181035f8301526101dd8185610175565b90506101ec60208301846101b6565b939250505056fe436865636b696e672076616c75652073746f72656420696e20322066726f6d206465706c6f79656420636f646520697320616363657369626c65436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c65436865636b696e672076616c75652073746f72656420696e20312066726f6d20636f6e7374727563746f7220697320616363657369626c65a264697066735822122016cae860d0cda920784f1ab4923dc095d7567876a114712426ec01cebbc6b2d464736f6c634300081a0033436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c6520696e20636f6e7374727563746f72a2646970667358221220da71a4ccc0ab9bca47a26db221968eb2cee1c312408b5ce77ce1aeecd4e8459164736f6c634300081a0033 + +6fc13818: testAcrossConstructorAndCodeV1() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCreateContextsContract contract +transaction_build txTestTransientStorageCreateContextsContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f80fd5b506107cd8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80636fc138181461002d575b5f80fd5b610035610037565b005b61003f6100ce565b5f60405161004c90610238565b604051809103905ff080158015610065573d5f803e3d5ffd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663a45449eb6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156100ad575f80fd5b505af11580156100bf573d5f803e3d5ffd5b505050506100cb6100e2565b50565b60025f5d600360015d600460025d365f8037565b5f805f805c925060015c915060025c9050610136836040518060400160405280601381526020017f436865636b696e672076616c756520696e20300000000000000000000000000081525060025f1b6101c1565b610179826040518060400160405280601381526020017f436865636b696e672076616c756520696e20310000000000000000000000000081525060035f1b6101c1565b6101bc816040518060400160405280601381526020017f436865636b696e672076616c756520696e20320000000000000000000000000081525060045f1b6101c1565b505050565b8083036101f9577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610233565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161022a9291906102cd565b60405180910390a15b505050565b61049c806102fc83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61028782610245565b610291818561024f565b93506102a181856020860161025f565b6102aa8161026d565b840191505092915050565b5f819050919050565b6102c7816102b5565b82525050565b5f6040820190508181035f8301526102e5818561027d565b90506102f460208301846102be565b939250505056fe608060405234801561000f575f80fd5b505f805c905061033360015d61004681604051806080016040528060458152602001610457604591395f801b61004c60201b60201c565b50610179565b808303610084577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100be565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd382846040516100b592919061014b565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610105826100c3565b61010f81856100cd565b935061011f8185602086016100dd565b610128816100eb565b840191505092915050565b5f819050919050565b61014581610133565b82525050565b5f6040820190508181035f83015261016381856100fb565b9050610172602083018461013c565b9392505050565b6102d1806101865f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063a45449eb1461002d575b5f80fd5b610035610037565b005b5f805f805c925060015c915061044460025d60025c90506100738360405180606001604052806036815260200161022e603691395f801b6100c6565b61009a82604051806060016040528060388152602001610264603891396103335f1b6100c6565b6100c1816040518060600160405280603a81526020016101f4603a91396104445f1b6100c6565b505050565b8083036100fe577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610138565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161012f9291906101c5565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61017f8261013d565b6101898185610147565b9350610199818560208601610157565b6101a281610165565b840191505092915050565b5f819050919050565b6101bf816101ad565b82525050565b5f6040820190508181035f8301526101dd8185610175565b90506101ec60208301846101b6565b939250505056fe436865636b696e672076616c75652073746f72656420696e20322066726f6d206465706c6f79656420636f646520697320616363657369626c65436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c65436865636b696e672076616c75652073746f72656420696e20312066726f6d20636f6e7374727563746f7220697320616363657369626c65a264697066735822122016cae860d0cda920784f1ab4923dc095d7567876a114712426ec01cebbc6b2d464736f6c634300081a0033436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c6520696e20636f6e7374727563746f72a2646970667358221220da71a4ccc0ab9bca47a26db221968eb2cee1c312408b5ce77ce1aeecd4e8459164736f6c634300081a0033 + gas 1000000 + build + +# Create block to hold txTestTransientStorageCreateContextsContract transaction +block_build b01 + parent g00 + transactions txTestTransientStorageCreateContextsContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txInConstructorAndCode transaction +transaction_build txAcrossConstructorAndCodeV1 + sender acc1 + nonce 1 + contract txTestTransientStorageCreateContextsContract + value 0 + data 6fc13818 + gas 1000000 + build + +# Create block to hold txAcrossConstructorAndCodeV1 transaction +block_build b02 + parent b01 + transactions txAcrossConstructorAndCodeV1 + gasLimit 3000000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_call_subcall.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_call_subcall.txt new file mode 100644 index 00000000000..7d6f256c59a --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_call_subcall.txt @@ -0,0 +1,127 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TestTransientStorageCallContext { + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function testCall() external { + // Deploy the Callee contract + address calleeAddress = address(new Callee()); + uint256 success; + uint256 valueLoadedFrom0; + uint256 valueLoadedFrom1; + uint256 valueLoadedSstore0; + uint256 valueLoadedSstore1; + bytes4 executeSignature = bytes4(keccak256("execute()")); + + assembly { + tstore(0, 420) + let availablePointer := mload(0x40) + mstore(availablePointer, executeSignature) + success := call(gas(), calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + valueLoadedFrom0 := tload(0) + valueLoadedFrom1 := tload(1) + valueLoadedSstore0 := sload(0) + valueLoadedSstore1 := sload(1) + } + + checkReturnValueExpected(success, 'Checking result callee execution', 1); + checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420); + checkReturnValueExpected(valueLoadedFrom1, 'Checking value from tload 1', 0); + + checkReturnValueExpected(valueLoadedSstore0, 'Checking value from sstore 0', 0); + checkReturnValueExpected(valueLoadedSstore1, 'Checking value from sstore 1', 0); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + event OK(); + event ERROR(string, uint256); + + function execute() external { + uint256 valueLoadedFrom1; + assembly { + sstore(0, tload(0)) + tstore(1, 69) + sstore(1, tload(1)) + valueLoadedFrom1 := tload(1) + } + if( valueLoadedFrom1 == 69){ + emit OK(); + } else { + emit ERROR('Checking value from tload 1 in callee', valueLoadedFrom1); + } + } +} + +// CONTRACT BYTECODE + +TestTransientStorageCallContext: 6080604052348015600e575f5ffd5b506105458061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063b7f058361461002d575b5f5ffd5b610035610037565b005b5f60405161004490610276565b604051809103905ff08015801561005d573d5f5f3e3d5ffd5b5090505f5f5f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6040518181526020816004835f8c5af196505f5c955060015c94505f5493506001549250506100f4866040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e81525060016101ff565b610136856040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101ff565b610176846040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152505f6101ff565b6101b6836040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652030000000008152505f6101ff565b6101f6826040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652031000000008152505f6101ff565b50505050505050565b808303610237577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610271565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161026892919061030b565b60405180910390a15b505050565b6101d68061033a83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102c582610283565b6102cf818561028d565b93506102df81856020860161029d565b6102e8816102ab565b840191505092915050565b5f819050919050565b610305816102f3565b82525050565b5f6040820190508181035f83015261032381856102bb565b905061033260208301846102fc565b939250505056fe6080604052348015600e575f5ffd5b506101ba8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063614619541461002d575b5f5ffd5b610035610037565b005b5f5f5c5f55604560015d60015c60015560015c905060458103610085577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100bd565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f816040516100b49190610158565b60405180910390a15b50565b5f82825260208201905092915050565b7f436865636b696e672076616c75652066726f6d20746c6f6164203120696e20635f8201527f616c6c6565000000000000000000000000000000000000000000000000000000602082015250565b5f61012a6025836100c0565b9150610135826100d0565b604082019050919050565b5f819050919050565b61015281610140565b82525050565b5f6040820190508181035f83015261016f8161011e565b905061017e6020830184610149565b9291505056fea2646970667358221220525015013274fe464b5371de8d79b5a498b2073f16a0ead556b61bb8daa945d664736f6c634300081c0033a2646970667358221220fe0d0f67ed34e641f6305bc910b9eb817769785a12a0f1837fe2371e930c5d1a64736f6c634300081c0033 + +b7f05836: testCall() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCallContext contract +transaction_build txContextCallSubcallContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f5ffd5b506105458061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063b7f058361461002d575b5f5ffd5b610035610037565b005b5f60405161004490610276565b604051809103905ff08015801561005d573d5f5f3e3d5ffd5b5090505f5f5f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6040518181526020816004835f8c5af196505f5c955060015c94505f5493506001549250506100f4866040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e81525060016101ff565b610136856040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101ff565b610176846040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152505f6101ff565b6101b6836040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652030000000008152505f6101ff565b6101f6826040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652031000000008152505f6101ff565b50505050505050565b808303610237577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610271565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161026892919061030b565b60405180910390a15b505050565b6101d68061033a83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102c582610283565b6102cf818561028d565b93506102df81856020860161029d565b6102e8816102ab565b840191505092915050565b5f819050919050565b610305816102f3565b82525050565b5f6040820190508181035f83015261032381856102bb565b905061033260208301846102fc565b939250505056fe6080604052348015600e575f5ffd5b506101ba8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063614619541461002d575b5f5ffd5b610035610037565b005b5f5f5c5f55604560015d60015c60015560015c905060458103610085577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100bd565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f816040516100b49190610158565b60405180910390a15b50565b5f82825260208201905092915050565b7f436865636b696e672076616c75652066726f6d20746c6f6164203120696e20635f8201527f616c6c6565000000000000000000000000000000000000000000000000000000602082015250565b5f61012a6025836100c0565b9150610135826100d0565b604082019050919050565b5f819050919050565b61015281610140565b82525050565b5f6040820190508181035f83015261016f8161011e565b905061017e6020830184610149565b9291505056fea2646970667358221220525015013274fe464b5371de8d79b5a498b2073f16a0ead556b61bb8daa945d664736f6c634300081c0033a2646970667358221220fe0d0f67ed34e641f6305bc910b9eb817769785a12a0f1837fe2371e930c5d1a64736f6c634300081c0033 + gas 1000000 + build + +# Create block to hold txContextCallSubcallContract transaction +block_build b01 + parent g00 + transactions txContextCallSubcallContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txExecuteCallCode transaction +transaction_build txExecuteCallCode + sender acc1 + nonce 1 + contract txContextCallSubcallContract + value 0 + data b7f05836 + gas 1000000 + build + +# Create block to hold txExecuteCallCode transaction +block_build b02 + parent b01 + transactions txExecuteCallCode + gasLimit 2000000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_simple.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_simple.txt new file mode 100644 index 00000000000..cdc4bf846ab --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_simple.txt @@ -0,0 +1,134 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TestTransientStorageCallAndDelegateCall { + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function testCallCodeAndDelegateCall(uint256 useCallCode) external { + // Deploy the Callee contract + address calleeAddress = address(new Callee()); + uint256 success; + uint256 valueLoadedFrom0; + uint256 valueLoadedFrom1; + uint256 valueLoadedSstore2; + uint256 valueLoadedSstore3; + bytes4 executeSignature = bytes4(keccak256("execute()")); + + assembly { + tstore(0, 420) + let availablePointer := mload(0x40) + mstore(availablePointer, executeSignature) + + // If useCallCode is 0, execute callCode otherwise execute delegateCall + switch useCallCode + case 1 { + success := callcode(gas(), calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + default { + success := delegatecall(gas(), calleeAddress, availablePointer, 0x4, availablePointer, 0x20) + } + valueLoadedFrom0 := tload(0) + valueLoadedSstore2 := sload(2) + valueLoadedSstore3 := sload(3) + valueLoadedFrom1 := tload(1) + } + + checkReturnValueExpected(success, 'Checking result callee execution', 1); + checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420); + checkReturnValueExpected(valueLoadedSstore2, 'Checking value from sstore 2', 420); + checkReturnValueExpected(valueLoadedSstore3, 'Checking value from sstore 3', 69); + checkReturnValueExpected(valueLoadedFrom1, 'Checking value from tload 1', 69); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + function execute() external { + assembly { + sstore(2, tload(0)) + tstore(1, 69) + sstore(3, tload(1)) + } + } +} + +// CONTRACT BYTECODE + +TestTransientStorageCallAndDelegateCall: 6080604052348015600e575f5ffd5b5061048e8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063a61face91461002d575b5f5ffd5b610047600480360381019061004291906102ec565b610049565b005b5f604051610056906102a9565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d60405181815288600181146100bf576020826004848c5af497506100cc565b6020826004845f8d5af297505b505f5c95506002549350600354925060015c945050610122866040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152506001610232565b610164856040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a4610232565b6101a6836040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652032000000008152506101a4610232565b6101e7826040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652033000000008152506045610232565b610228846040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506045610232565b5050505050505050565b80830361026a577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16102a4565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161029b929190610396565b60405180910390a15b505050565b6094806103c583390190565b5f5ffd5b5f819050919050565b6102cb816102b9565b81146102d5575f5ffd5b50565b5f813590506102e6816102c2565b92915050565b5f60208284031215610301576103006102b5565b5b5f61030e848285016102d8565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61035982610317565b6103638185610321565b9350610373818560208601610331565b61037c8161033f565b840191505092915050565b610390816102b9565b82525050565b5f6040820190508181035f8301526103ae818561034f565b90506103bd6020830184610387565b939250505056fe6080604052348015600e575f5ffd5b50607a80601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b5f5c600255604560015d60015c60035556fea26469706673582212201771c67495697664bc8f0b297a683b4e7dbb7e31feaf9cf735faf209a14d64fa64736f6c634300081c0033a2646970667358221220ce4a7e6da5344a1d5a34ebef6c0267ac15796a3a9529427da9ba17a9cc4bee0864736f6c634300081c0033 + +a61face9: testCallCodeAndDelegateCall(uint256) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCallAndDelegateCall contract +transaction_build txCallAndDelegateCallSimpleTest + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f5ffd5b5061048e8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063a61face91461002d575b5f5ffd5b610047600480360381019061004291906102ec565b610049565b005b5f604051610056906102a9565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d60405181815288600181146100bf576020826004848c5af497506100cc565b6020826004845f8d5af297505b505f5c95506002549350600354925060015c945050610122866040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152506001610232565b610164856040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a4610232565b6101a6836040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652032000000008152506101a4610232565b6101e7826040518060400160405280601c81526020017f436865636b696e672076616c75652066726f6d207373746f72652033000000008152506045610232565b610228846040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506045610232565b5050505050505050565b80830361026a577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16102a4565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161029b929190610396565b60405180910390a15b505050565b6094806103c583390190565b5f5ffd5b5f819050919050565b6102cb816102b9565b81146102d5575f5ffd5b50565b5f813590506102e6816102c2565b92915050565b5f60208284031215610301576103006102b5565b5b5f61030e848285016102d8565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61035982610317565b6103638185610321565b9350610373818560208601610331565b61037c8161033f565b840191505092915050565b610390816102b9565b82525050565b5f6040820190508181035f8301526103ae818561034f565b90506103bd6020830184610387565b939250505056fe6080604052348015600e575f5ffd5b50607a80601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b5f5c600255604560015d60015c60035556fea26469706673582212201771c67495697664bc8f0b297a683b4e7dbb7e31feaf9cf735faf209a14d64fa64736f6c634300081c0033a2646970667358221220ce4a7e6da5344a1d5a34ebef6c0267ac15796a3a9529427da9ba17a9cc4bee0864736f6c634300081c0033 + gas 1000000 + build + +# Create block to hold txCallAndDelegateCallSimpleTest transaction +block_build b01 + parent g00 + transactions txCallAndDelegateCallSimpleTest + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txExecuteCallCode transaction +transaction_build txExecuteCallCode + sender acc1 + nonce 1 + contract txCallAndDelegateCallSimpleTest + value 0 + data a61face90000000000000000000000000000000000000000000000000000000000000001 + gas 300000 + build + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteDelegateCall + sender acc1 + nonce 2 + contract txCallAndDelegateCallSimpleTest + value 0 + data a61face90000000000000000000000000000000000000000000000000000000000000000 + gas 300000 + build + +# Create block to hold transactions +block_build b02 + parent b01 + transactions txExecuteCallCode txExecuteDelegateCall + gasLimit 1500000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_staticcall_subcall_can_call_tload.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_staticcall_subcall_can_call_tload.txt new file mode 100644 index 00000000000..23ec7b497ea --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_staticcall_subcall_can_call_tload.txt @@ -0,0 +1,105 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TstorageExecutionContextsStaticCallCanCallTload { + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function testStaticCall() external { + // Deploy the Callee contract + address calleeAddress = address(new Callee()); + uint256 success; + uint256 valueLoadedFrom0; + bytes4 executeSignature = bytes4(keccak256("execute()")); + + assembly { + tstore(0, 420) + let availablePointer := mload(0x40) + mstore(availablePointer, executeSignature) + success := staticcall(gas(), calleeAddress, availablePointer, 0x4, availablePointer, 0x20) + valueLoadedFrom0 := tload(0) + } + + checkReturnValueExpected(success, 'Checking result callee execution', 1); + checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + function execute() external { + uint256 valueLoadedFrom0; + assembly { + valueLoadedFrom0 := tload(0) + } + } +} +// CONTRACT BYTECODE + +TstorageExecutionContextsStaticCallCanCallTload: 608060405234801561000f575f80fd5b5061033d8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063d411defb1461002d575b5f80fd5b610035610037565b005b5f604051610044906101a1565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f805f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d604051818152602081600483885afa93505f5c9250506100e2836040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e815250600161012a565b610124826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a461012a565b50505050565b808303610162577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161019c565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161019392919061024f565b60405180910390a15b505050565b608a8061027e83390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101e45780820151818401526020810190506101c9565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610209826101ad565b61021381856101b7565b93506102238185602086016101c7565b61022c816101ef565b840191505092915050565b5f819050919050565b61024981610237565b82525050565b5f6040820190508181035f83015261026781856101ff565b90506102766020830184610240565b939250505056fe6080604052348015600e575f80fd5b50607080601a5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c80636146195414602a575b5f80fd5b60306032565b005b5f805c90505056fea26469706673582212208f7b43026cae3d8abeeba9ec0dbacdfc50382579f514a511fcb33502ea8b0b3164736f6c63430008180033a2646970667358221220faf33c612e077d0439d4663f3700736865523f14d281f5a1ac59f82062390bd664736f6c63430008180033 + +d411defb: testStaticCall() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstorageExecutionContextsStaticCallCanCallTload contract +transaction_build txContextStaticCallCanCallTloadContract + sender acc1 + receiverAddress 00 + value 0 + data 608060405234801561000f575f80fd5b5061033d8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063d411defb1461002d575b5f80fd5b610035610037565b005b5f604051610044906101a1565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f805f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d604051818152602081600483885afa93505f5c9250506100e2836040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e815250600161012a565b610124826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a461012a565b50505050565b808303610162577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161019c565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161019392919061024f565b60405180910390a15b505050565b608a8061027e83390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101e45780820151818401526020810190506101c9565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610209826101ad565b61021381856101b7565b93506102238185602086016101c7565b61022c816101ef565b840191505092915050565b5f819050919050565b61024981610237565b82525050565b5f6040820190508181035f83015261026781856101ff565b90506102766020830184610240565b939250505056fe6080604052348015600e575f80fd5b50607080601a5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c80636146195414602a575b5f80fd5b60306032565b005b5f805c90505056fea26469706673582212208f7b43026cae3d8abeeba9ec0dbacdfc50382579f514a511fcb33502ea8b0b3164736f6c63430008180033a2646970667358221220faf33c612e077d0439d4663f3700736865523f14d281f5a1ac59f82062390bd664736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txContextStaticCallCanCallTloadContract transaction +block_build b01 + parent g00 + transactions txContextStaticCallCanCallTloadContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txExecuteStaticCallCode transaction +transaction_build txExecuteStaticCallCode + sender acc1 + nonce 1 + contract txContextStaticCallCanCallTloadContract + value 0 + data d411defb + gas 1000000 + build + +# Create block to hold txExecuteStaticCallCode transaction +block_build b02 + parent b01 + transactions txExecuteStaticCallCode + gasLimit 2000000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_staticcall_subcall_cant_call_tstore.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_staticcall_subcall_cant_call_tstore.txt new file mode 100644 index 00000000000..4bc0112232a --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_staticcall_subcall_cant_call_tstore.txt @@ -0,0 +1,106 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TstorageExecutionContextsStaticCallCantCallTstore { + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function testCall() external { + // Deploy the Callee contract + address calleeAddress = address(new Callee()); + uint256 success; + uint256 valueLoadedFrom0; + bytes4 executeSignature = bytes4(keccak256("execute()")); + + assembly { + tstore(0, 420) + let availablePointer := mload(0x40) + mstore(availablePointer, executeSignature) + success := staticcall(0xFFFF, calleeAddress, availablePointer, 0x4, availablePointer, 0x20) + valueLoadedFrom0 := tload(0) + } + + checkReturnValueExpected(success, 'Checking result callee execution fails', 0); + checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + + function execute() external { + assembly { + tstore(1, 69) + } + } +} + +// CONTRACT BYTECODE + +TstorageExecutionContextsStaticCallCantCallTstore: 608060405234801561000f575f80fd5b506103468061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063d411defb1461002d575b5f80fd5b610035610037565b005b5f60405161004490610185565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f805f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6040518181526020816004838861fffffa93505f5c9250506100c6836040518060600160405280602681526020016102eb602691395f61010e565b610108826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a461010e565b50505050565b808303610146577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610180565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610177929190610233565b60405180910390a15b505050565b60898061026283390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101c85780820151818401526020810190506101ad565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6101ed82610191565b6101f7818561019b565b93506102078185602086016101ab565b610210816101d3565b840191505092915050565b5f819050919050565b61022d8161021b565b82525050565b5f6040820190508181035f83015261024b81856101e3565b905061025a6020830184610224565b939250505056fe6080604052348015600e575f80fd5b50606f80601a5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c80636146195414602a575b5f80fd5b60306032565b005b604560015d56fea2646970667358221220a5f01eceb4465312039e37fe5b8913c77743ea042f64eb0e55a16f3e422abde864736f6c63430008180033436865636b696e6720726573756c742063616c6c656520657865637574696f6e206661696c73a2646970667358221220c2660b49032f7ee7ddf39afb75369768bfdc123aa7021d49df042a9ba368053164736f6c63430008180033 + +d411defb: testStaticCall() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstorageExecutionContextsStaticCallCantCallTstore contract +transaction_build txContextStaticCallCantCallTstoreContract + sender acc1 + receiverAddress 00 + value 0 + data 608060405234801561000f575f80fd5b506103468061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063d411defb1461002d575b5f80fd5b610035610037565b005b5f60405161004490610185565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f805f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6040518181526020816004838861fffffa93505f5c9250506100c6836040518060600160405280602681526020016102eb602691395f61010e565b610108826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a461010e565b50505050565b808303610146577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610180565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610177929190610233565b60405180910390a15b505050565b60898061026283390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101c85780820151818401526020810190506101ad565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6101ed82610191565b6101f7818561019b565b93506102078185602086016101ab565b610210816101d3565b840191505092915050565b5f819050919050565b61022d8161021b565b82525050565b5f6040820190508181035f83015261024b81856101e3565b905061025a6020830184610224565b939250505056fe6080604052348015600e575f80fd5b50606f80601a5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c80636146195414602a575b5f80fd5b60306032565b005b604560015d56fea2646970667358221220a5f01eceb4465312039e37fe5b8913c77743ea042f64eb0e55a16f3e422abde864736f6c63430008180033436865636b696e6720726573756c742063616c6c656520657865637574696f6e206661696c73a2646970667358221220c2660b49032f7ee7ddf39afb75369768bfdc123aa7021d49df042a9ba368053164736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txContextStaticCallCantCallTstoreContract transaction +block_build b01 + parent g00 + transactions txContextStaticCallCantCallTstoreContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txExecuteStaticCallCode transaction +transaction_build txExecuteStaticCallCode + sender acc1 + nonce 1 + contract txContextStaticCallCantCallTstoreContract + value 0 + data d411defb + gas 1000000 + build + +# Create block to hold txExecuteStaticCallCode transaction +block_build b02 + parent b01 + transactions txExecuteStaticCallCode + gasLimit 2000000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_with_invalid.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_with_invalid.txt new file mode 100644 index 00000000000..6064b09506b --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_with_invalid.txt @@ -0,0 +1,140 @@ +comment +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TestTStorageDynamicExecutionContextWithInvalid{ + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function testCallSelectingContractCallOpcode(uint256 contractCallSelector) external { + // Deploy the Callee contract + address calleeAddress = address(new Callee()); + uint256 success; + uint256 valueLoadedFrom0; + uint256 valueLoadedFrom1; + bytes4 executeSignature = bytes4(keccak256("execute()")); + + assembly { + tstore(0, 420) + tstore(1, 420) + + let availablePointer := mload(0x40) + mstore(availablePointer, executeSignature) + // If useDelegateCall is greater than 0, execute delegateCall otherwise execute callCode + switch contractCallSelector + case 0 { + success := callcode(0xFF, calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + case 1 { + success := delegatecall(0xFF, calleeAddress, availablePointer, 0x4, availablePointer, 0x20) + } + default { + success := call(0xFF, calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + valueLoadedFrom0 := tload(0) + valueLoadedFrom1 := tload(1) + } + + checkReturnValueExpected(success, 'Checking result callee execution', 0); + checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420); + checkReturnValueExpected(valueLoadedFrom1, 'Checking value from tload 1', 420); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + function execute() external { + assembly { + tstore(1, 69) + invalid() + } + } +} + +// CONTRACT BYTECODE + +TestTStorageDynamicExecutionContextWithInvalid: 6080604052348015600e575f5ffd5b506104138061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b6100476004803603810190610042919061027c565b610049565b005b5f60405161005690610239565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cc57600181146100de576020826004845f8b60fff195506100eb565b6020826004845f8b60fff295506100eb565b6020826004848a60fff495505b505f5c935060015c925050610136846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101c2565b610178836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101c2565b6101ba826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101c2565b505050505050565b8083036101fa577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610234565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161022b929190610326565b60405180910390a15b505050565b60898061035583390190565b5f5ffd5b5f819050919050565b61025b81610249565b8114610265575f5ffd5b50565b5f8135905061027681610252565b92915050565b5f6020828403121561029157610290610245565b5b5f61029e84828501610268565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102e9826102a7565b6102f381856102b1565b93506103038185602086016102c1565b61030c816102cf565b840191505092915050565b61032081610249565b82525050565b5f6040820190508181035f83015261033e81856102df565b905061034d6020830184610317565b939250505056fe6080604052348015600e575f5ffd5b50606f80601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b604560015dfefea26469706673582212207c61e75cb53c4ad046d081a86c932bf15e83580e0d3ceae3fa417efcab11607e64736f6c634300081c0033a264697066735822122099e5211521504bd8cd35e3f045924e1065174f722e1fb24d137b65571be0fbb364736f6c634300081c0033 + +9823c406: testCallSelectingContractCallOpcode(uint256) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCallAndDelegateCall contract +transaction_build txDynamicExecutionContextWithInvalidTest + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f5ffd5b506104138061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b6100476004803603810190610042919061027c565b610049565b005b5f60405161005690610239565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cc57600181146100de576020826004845f8b60fff195506100eb565b6020826004845f8b60fff295506100eb565b6020826004848a60fff495505b505f5c935060015c925050610136846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101c2565b610178836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101c2565b6101ba826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101c2565b505050505050565b8083036101fa577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610234565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161022b929190610326565b60405180910390a15b505050565b60898061035583390190565b5f5ffd5b5f819050919050565b61025b81610249565b8114610265575f5ffd5b50565b5f8135905061027681610252565b92915050565b5f6020828403121561029157610290610245565b5b5f61029e84828501610268565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102e9826102a7565b6102f381856102b1565b93506103038185602086016102c1565b61030c816102cf565b840191505092915050565b61032081610249565b82525050565b5f6040820190508181035f83015261033e81856102df565b905061034d6020830184610317565b939250505056fe6080604052348015600e575f5ffd5b50606f80601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b604560015dfefea26469706673582212207c61e75cb53c4ad046d081a86c932bf15e83580e0d3ceae3fa417efcab11607e64736f6c634300081c0033a264697066735822122099e5211521504bd8cd35e3f045924e1065174f722e1fb24d137b65571be0fbb364736f6c634300081c0033 + gas 1000000 + build + +# Create block to hold txDynamicExecutionContextWithInvalidTest transaction +block_build b01 + parent g00 + transactions txDynamicExecutionContextWithInvalidTest + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txExecuteCallCode transaction +transaction_build txExecuteCallCode + sender acc1 + nonce 1 + contract txDynamicExecutionContextWithInvalidTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000000 + gas 500000 + build + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteDelegateCall + sender acc1 + nonce 2 + contract txDynamicExecutionContextWithInvalidTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000001 + gas 500000 + build + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteCall + sender acc1 + nonce 3 + contract txDynamicExecutionContextWithInvalidTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000002 + gas 500000 + build + +# Create block to hold transactions +block_build b02 + parent b01 + transactions txExecuteCallCode txExecuteDelegateCall txExecuteCall + gasLimit 2000000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_with_revert.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_with_revert.txt new file mode 100644 index 00000000000..05446336061 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_with_revert.txt @@ -0,0 +1,140 @@ +comment +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TestTStorageDynamicExecutionContextWithRevert { + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function testCallSelectingContractCallOpcode(uint256 contractCallSelector) external { + // Deploy the Callee contract + address calleeAddress = address(new Callee()); + uint256 success; + uint256 valueLoadedFrom0; + uint256 valueLoadedFrom1; + bytes4 executeSignature = bytes4(keccak256("execute()")); + + assembly { + tstore(0, 420) + tstore(1, 420) + + let availablePointer := mload(0x40) + mstore(availablePointer, executeSignature) + // If useDelegateCall is greater than 0, execute delegateCall otherwise execute callCode + switch contractCallSelector + case 0 { + success := callcode(gas(), calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + case 1 { + success := delegatecall(gas(), calleeAddress, availablePointer, 0x4, availablePointer, 0x20) + } + default { + success := call(gas(), calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + valueLoadedFrom0 := tload(0) + valueLoadedFrom1 := tload(1) + } + + checkReturnValueExpected(success, 'Checking result callee execution', 0); + checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420); + checkReturnValueExpected(valueLoadedFrom1, 'Checking value from tload 1', 420); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + function execute() external { + assembly { + tstore(1, 69) + revert(0,0) + } + } +} + +// CONTRACT BYTECODE + +TestTStorageDynamicExecutionContextWithRevert: 6080604052348015600e575f5ffd5b506104128061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b61004760048036038101906100429190610279565b610049565b005b5f60405161005690610236565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cb57600181146100dc576020826004845f8b5af195506100e8565b6020826004845f8b5af295506100e8565b6020826004848a5af495505b505f5c935060015c925050610133846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101bf565b610175836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101bf565b6101b7826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101bf565b505050505050565b8083036101f7577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610231565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610228929190610323565b60405180910390a15b505050565b608b8061035283390190565b5f5ffd5b5f819050919050565b61025881610246565b8114610262575f5ffd5b50565b5f813590506102738161024f565b92915050565b5f6020828403121561028e5761028d610242565b5b5f61029b84828501610265565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102e6826102a4565b6102f081856102ae565b93506103008185602086016102be565b610309816102cc565b840191505092915050565b61031d81610246565b82525050565b5f6040820190508181035f83015261033b81856102dc565b905061034a6020830184610314565b939250505056fe6080604052348015600e575f5ffd5b50607180601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b604560015d5f5ffdfea264697066735822122012b2acf84430846181c2090e00f142a45789288a3094ef935604fa5b2cb44e1f64736f6c634300081c0033a26469706673582212200323b022738aab6530f9ff3cde3c2b7774d6dc76d7ee932e8bd4edb7b517a59064736f6c634300081c0033 + +9823c406: testCallSelectingContractCallOpcode(uint256) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCallAndDelegateCall contract +transaction_build txDynamicExecutionContextWithRevertTest + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f5ffd5b506104128061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b61004760048036038101906100429190610279565b610049565b005b5f60405161005690610236565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cb57600181146100dc576020826004845f8b5af195506100e8565b6020826004845f8b5af295506100e8565b6020826004848a5af495505b505f5c935060015c925050610133846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101bf565b610175836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101bf565b6101b7826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101bf565b505050505050565b8083036101f7577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610231565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610228929190610323565b60405180910390a15b505050565b608b8061035283390190565b5f5ffd5b5f819050919050565b61025881610246565b8114610262575f5ffd5b50565b5f813590506102738161024f565b92915050565b5f6020828403121561028e5761028d610242565b5b5f61029b84828501610265565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102e6826102a4565b6102f081856102ae565b93506103008185602086016102be565b610309816102cc565b840191505092915050565b61031d81610246565b82525050565b5f6040820190508181035f83015261033b81856102dc565b905061034a6020830184610314565b939250505056fe6080604052348015600e575f5ffd5b50607180601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c80636146195414602a575b5f5ffd5b60306032565b005b604560015d5f5ffdfea264697066735822122012b2acf84430846181c2090e00f142a45789288a3094ef935604fa5b2cb44e1f64736f6c634300081c0033a26469706673582212200323b022738aab6530f9ff3cde3c2b7774d6dc76d7ee932e8bd4edb7b517a59064736f6c634300081c0033 + gas 1000000 + build + +# Create block to hold txDynamicExecutionContextWithRevertTest transaction +block_build b01 + parent g00 + transactions txDynamicExecutionContextWithRevertTest + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txExecuteCallCode transaction +transaction_build txExecuteCallCode + sender acc1 + nonce 1 + contract txDynamicExecutionContextWithRevertTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000000 + gas 500000 + build + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteDelegateCall + sender acc1 + nonce 2 + contract txDynamicExecutionContextWithRevertTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000001 + gas 500000 + build + +# Create transaction to execute txExecuteCall transaction +transaction_build txExecuteCall + sender acc1 + nonce 3 + contract txDynamicExecutionContextWithRevertTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000002 + gas 500000 + build + +# Create block to hold transactions +block_build b02 + parent b01 + transactions txExecuteCallCode txExecuteDelegateCall txExecuteCall + gasLimit 2000000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_with_stack_overflow.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_with_stack_overflow.txt new file mode 100644 index 00000000000..040e7143202 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_execution_context_with_stack_overflow.txt @@ -0,0 +1,147 @@ +comment +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TestTStorageDynamicExecutionContextWithStackOverflow { + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function testCallSelectingContractCallOpcode(uint256 contractCallSelector) external { + // Deploy the Callee contract + address calleeAddress = address(new Callee()); + uint256 success; + uint256 valueLoadedFrom0; + uint256 valueLoadedFrom1; + bytes4 executeSignature = bytes4(keccak256("execute()")); + + assembly { + tstore(0, 420) + tstore(1, 420) + + let availablePointer := mload(0x40) + mstore(availablePointer, executeSignature) + // If useDelegateCall is greater than 0, execute delegateCall otherwise execute callCode + switch contractCallSelector + case 0 { + success := callcode(0xFFFF, calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + case 1 { + success := delegatecall(0xFFFF, calleeAddress, availablePointer, 0x4, availablePointer, 0x20) + } + default { + success := call(0xFFFF, calleeAddress, 0, availablePointer, 0x4, availablePointer, 0x20) + } + valueLoadedFrom0 := tload(0) + valueLoadedFrom1 := tload(1) + } + + checkReturnValueExpected(success, 'Checking result callee execution', 0); + checkReturnValueExpected(valueLoadedFrom0, 'Checking value from tload 0', 420); + checkReturnValueExpected(valueLoadedFrom1, 'Checking value from tload 1', 420); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + function execute() external { + assembly { + tstore(1,69) + } + this.executeRecursive(0); + } + + function executeRecursive(uint256 counter) external { + if(counter < 1026){ + counter ++; + this.executeRecursive(counter); + } + } +} + +// CONTRACT BYTECODE + +TestTStorageDynamicExecutionContextWithStackOverflow: 6080604052348015600e575f5ffd5b506106868061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b61004760048036038101906100429190610280565b610049565b005b5f6040516100569061023c565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cd57600181146100e0576020826004845f8b61fffff195506100ee565b6020826004845f8b61fffff295506100ee565b6020826004848a61fffff495505b505f5c935060015c925050610139846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101c5565b61017b836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101c5565b6101bd826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101c5565b505050505050565b8083036101fd577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610237565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161022e92919061032a565b60405180910390a15b505050565b6102f88061035983390190565b5f5ffd5b5f819050919050565b61025f8161024d565b8114610269575f5ffd5b50565b5f8135905061027a81610256565b92915050565b5f6020828403121561029557610294610249565b5b5f6102a28482850161026c565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102ed826102ab565b6102f781856102b5565b93506103078185602086016102c5565b610310816102d3565b840191505092915050565b6103248161024d565b82525050565b5f6040820190508181035f83015261034281856102e3565b9050610351602083018461031b565b939250505056fe6080604052348015600e575f5ffd5b506102dc8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c80636146195414610038578063fccbafb914610042575b5f5ffd5b61004061005e565b005b61005c60048036038101906100579190610184565b6100cb565b005b604560015d3073ffffffffffffffffffffffffffffffffffffffff1663fccbafb95f6040518263ffffffff1660e01b815260040161009c91906101f1565b5f604051808303815f87803b1580156100b3575f5ffd5b505af11580156100c5573d5f5f3e3d5ffd5b50505050565b61040281101561014a5780806100e090610237565b9150503073ffffffffffffffffffffffffffffffffffffffff1663fccbafb9826040518263ffffffff1660e01b815260040161011c919061028d565b5f604051808303815f87803b158015610133575f5ffd5b505af1158015610145573d5f5f3e3d5ffd5b505050505b50565b5f5ffd5b5f819050919050565b61016381610151565b811461016d575f5ffd5b50565b5f8135905061017e8161015a565b92915050565b5f602082840312156101995761019861014d565b5b5f6101a684828501610170565b91505092915050565b5f819050919050565b5f819050919050565b5f6101db6101d66101d1846101af565b6101b8565b610151565b9050919050565b6101eb816101c1565b82525050565b5f6020820190506102045f8301846101e2565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61024182610151565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036102735761027261020a565b5b600182019050919050565b61028781610151565b82525050565b5f6020820190506102a05f83018461027e565b9291505056fea26469706673582212208c06dbf10708fcc54598b88ca5465d5b4189bd294c289c13db194e75762635f764736f6c634300081c0033a2646970667358221220c007921bf7d900df9462a49fe9fca543537ec9f988ce2d601da8182ad224485364736f6c634300081c0033 + +9823c406: testCallSelectingContractCallOpcode(uint256) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCallAndDelegateCall contract +transaction_build txDynamicExecutionContextWithStackOverflowTest + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f5ffd5b506106868061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c80639823c4061461002d575b5f5ffd5b61004760048036038101906100429190610280565b610049565b005b5f6040516100569061023c565b604051809103905ff08015801561006f573d5f5f3e3d5ffd5b5090505f5f5f5f7f614619540b5b5abe478b88f28a37eb328054be3b41a7570ad5e8b701113364c490506101a45f5d6101a460015d604051818152865f81146100cd57600181146100e0576020826004845f8b61fffff195506100ee565b6020826004845f8b61fffff295506100ee565b6020826004848a61fffff495505b505f5c935060015c925050610139846040518060400160405280602081526020017f436865636b696e6720726573756c742063616c6c656520657865637574696f6e8152505f6101c5565b61017b836040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203000000000008152506101a46101c5565b6101bd826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d20746c6f6164203100000000008152506101a46101c5565b505050505050565b8083036101fd577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610237565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161022e92919061032a565b60405180910390a15b505050565b6102f88061035983390190565b5f5ffd5b5f819050919050565b61025f8161024d565b8114610269575f5ffd5b50565b5f8135905061027a81610256565b92915050565b5f6020828403121561029557610294610249565b5b5f6102a28482850161026c565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102ed826102ab565b6102f781856102b5565b93506103078185602086016102c5565b610310816102d3565b840191505092915050565b6103248161024d565b82525050565b5f6040820190508181035f83015261034281856102e3565b9050610351602083018461031b565b939250505056fe6080604052348015600e575f5ffd5b506102dc8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c80636146195414610038578063fccbafb914610042575b5f5ffd5b61004061005e565b005b61005c60048036038101906100579190610184565b6100cb565b005b604560015d3073ffffffffffffffffffffffffffffffffffffffff1663fccbafb95f6040518263ffffffff1660e01b815260040161009c91906101f1565b5f604051808303815f87803b1580156100b3575f5ffd5b505af11580156100c5573d5f5f3e3d5ffd5b50505050565b61040281101561014a5780806100e090610237565b9150503073ffffffffffffffffffffffffffffffffffffffff1663fccbafb9826040518263ffffffff1660e01b815260040161011c919061028d565b5f604051808303815f87803b158015610133575f5ffd5b505af1158015610145573d5f5f3e3d5ffd5b505050505b50565b5f5ffd5b5f819050919050565b61016381610151565b811461016d575f5ffd5b50565b5f8135905061017e8161015a565b92915050565b5f602082840312156101995761019861014d565b5b5f6101a684828501610170565b91505092915050565b5f819050919050565b5f819050919050565b5f6101db6101d66101d1846101af565b6101b8565b610151565b9050919050565b6101eb816101c1565b82525050565b5f6020820190506102045f8301846101e2565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61024182610151565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036102735761027261020a565b5b600182019050919050565b61028781610151565b82525050565b5f6020820190506102a05f83018461027e565b9291505056fea26469706673582212208c06dbf10708fcc54598b88ca5465d5b4189bd294c289c13db194e75762635f764736f6c634300081c0033a2646970667358221220c007921bf7d900df9462a49fe9fca543537ec9f988ce2d601da8182ad224485364736f6c634300081c0033 + gas 1000000 + build + +# Create block to hold txDynamicExecutionContextWithStackOverflowTest transaction +block_build b01 + parent g00 + transactions txDynamicExecutionContextWithStackOverflowTest + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txExecuteCallCode transaction +transaction_build txExecuteCallCode + sender acc1 + nonce 1 + contract txDynamicExecutionContextWithStackOverflowTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000000 + gas 500000 + build + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteDelegateCall + sender acc1 + nonce 2 + contract txDynamicExecutionContextWithStackOverflowTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000001 + gas 500000 + build + +# Create transaction to execute txExecuteDelegateCall transaction +transaction_build txExecuteCall + sender acc1 + nonce 3 + contract txDynamicExecutionContextWithStackOverflowTest + value 0 + data 9823c4060000000000000000000000000000000000000000000000000000000000000002 + gas 500000 + build + +# Create block to hold transactions +block_build b02 + parent b01 + transactions txExecuteCallCode txExecuteDelegateCall txExecuteCall + gasLimit 2000000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_reentrancy_context_revert_or_invalid_undoes_all.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_reentrancy_context_revert_or_invalid_undoes_all.txt new file mode 100644 index 00000000000..23f19e6fa2e --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_reentrancy_context_revert_or_invalid_undoes_all.txt @@ -0,0 +1,154 @@ +comment + +// CONTRACT CODE + +pragma solidity ^0.8.24; + +contract TstorageDynamicReentrancyContext { + bool reentrant = false; + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function opcodeUndoesAll(uint256 opcodeSelector) external { + bytes memory data = abi.encodeWithSignature("opcodeUndoesAll(uint256)", opcodeSelector); + uint256 fail; + uint256 valueLoadedFromFEBefore; + uint256 valueLoadedFromFFBefore; + uint256 valueLoadedFromFEAfter; + uint256 valueLoadedFromFFAfter; + + assembly { + let reentrantValue := sload(reentrant.slot) + switch reentrantValue + case 0 { + sstore(reentrant.slot, true) + + tstore(0xFE, 0x100) + tstore(0xFF, 0x101) + valueLoadedFromFEBefore := tload(0xFE) + valueLoadedFromFFBefore := tload(0xFF) + + mstore(0, 2) + switch opcodeSelector + case 0 { + fail := call(gas(), address(), 0, add(data, 0x20), mload(data), 0, 0) + } + case 1 { + fail := call(gas(), address(), 0, add(data, 0x20), mload(data), 0, 0) + } + valueLoadedFromFEAfter := tload(0xFE) + valueLoadedFromFFAfter := tload(0xFF) + + } + default { + tstore(0xFE, 0x201) + tstore(0xFE, 0x202) + tstore(0xFF, 0x201) + tstore(0xFF, 0x202) + switch opcodeSelector + case 0 { + revert(0, 0) + } + case 1 { + invalid() + } + } + } + checkReturnValueExpected(fail, 'Checking result callee execution fails', 0); + checkReturnValueExpected(valueLoadedFromFEBefore, 'Checking value from tload FE before', 0x100); + checkReturnValueExpected(valueLoadedFromFEAfter, 'Checking value from tload FE after', 0x100); + checkReturnValueExpected(valueLoadedFromFFBefore, 'Checking value from tload FF before', 0x101); + checkReturnValueExpected(valueLoadedFromFFAfter, 'Checking value from tload FF after', 0x101); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TstorageDynamicReentrancyContext: 60806040525f805f6101000a81548160ff021916908315150217905550348015610027575f80fd5b506104e4806100355f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630b35f95c1461002d575b5f80fd5b610047600480360381019061004291906102f3565b610049565b005b5f8160405160240161005b919061032d565b6040516020818303038152906040527f0b35f95c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f805f805f8054805f81146101225761020160fe5d61020260fe5d61020160ff5d61020260ff5d885f8114610116576001811461011a5761011c565b5f80fd5bfe5b50610183565b60015f5561010060fe5d61010160ff5d60fe5c955060ff5c945060025f52885f8114610155576001811461016857610177565b5f808a5160208c015f305af19750610177565b5f808a5160208c015f305af197505b5060fe5c935060ff5c92505b50506101a885604051806060016040528060268152602001610421602691395f610245565b6101cd8460405180606001604052806023815260200161046960239139610100610245565b6101f28260405180606001604052806022815260200161044760229139610100610245565b6102178360405180606001604052806023815260200161048c60239139610101610245565b61023c816040518060600160405280602281526020016103ff60229139610101610245565b50505050505050565b80830361027d577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16102b7565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516102ae9291906103d0565b60405180910390a15b505050565b5f80fd5b5f819050919050565b6102d2816102c0565b81146102dc575f80fd5b50565b5f813590506102ed816102c9565b92915050565b5f60208284031215610308576103076102bc565b5b5f610315848285016102df565b91505092915050565b610327816102c0565b82525050565b5f6020820190506103405f83018461031e565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561037d578082015181840152602081019050610362565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6103a282610346565b6103ac8185610350565b93506103bc818560208601610360565b6103c581610388565b840191505092915050565b5f6040820190508181035f8301526103e88185610398565b90506103f7602083018461031e565b939250505056fe436865636b696e672076616c75652066726f6d20746c6f6164204646206166746572436865636b696e6720726573756c742063616c6c656520657865637574696f6e206661696c73436865636b696e672076616c75652066726f6d20746c6f6164204645206166746572436865636b696e672076616c75652066726f6d20746c6f6164204645206265666f7265436865636b696e672076616c75652066726f6d20746c6f6164204646206265666f7265a264697066735822122014d79ec53d86680fbb087e64cebf51f7c1e829ea7683527c492cf3316530d26964736f6c63430008180033 + +0b35f95c: opcodeUndoesAll(uint256) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstorageDynamicReentrancyContext contract +transaction_build txTstorageDynamicReentrancyContextContract + sender acc1 + receiverAddress 00 + value 0 + data 60806040525f805f6101000a81548160ff021916908315150217905550348015610027575f80fd5b506104e4806100355f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630b35f95c1461002d575b5f80fd5b610047600480360381019061004291906102f3565b610049565b005b5f8160405160240161005b919061032d565b6040516020818303038152906040527f0b35f95c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f805f805f8054805f81146101225761020160fe5d61020260fe5d61020160ff5d61020260ff5d885f8114610116576001811461011a5761011c565b5f80fd5bfe5b50610183565b60015f5561010060fe5d61010160ff5d60fe5c955060ff5c945060025f52885f8114610155576001811461016857610177565b5f808a5160208c015f305af19750610177565b5f808a5160208c015f305af197505b5060fe5c935060ff5c92505b50506101a885604051806060016040528060268152602001610421602691395f610245565b6101cd8460405180606001604052806023815260200161046960239139610100610245565b6101f28260405180606001604052806022815260200161044760229139610100610245565b6102178360405180606001604052806023815260200161048c60239139610101610245565b61023c816040518060600160405280602281526020016103ff60229139610101610245565b50505050505050565b80830361027d577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16102b7565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516102ae9291906103d0565b60405180910390a15b505050565b5f80fd5b5f819050919050565b6102d2816102c0565b81146102dc575f80fd5b50565b5f813590506102ed816102c9565b92915050565b5f60208284031215610308576103076102bc565b5b5f610315848285016102df565b91505092915050565b610327816102c0565b82525050565b5f6020820190506103405f83018461031e565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561037d578082015181840152602081019050610362565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6103a282610346565b6103ac8185610350565b93506103bc818560208601610360565b6103c581610388565b840191505092915050565b5f6040820190508181035f8301526103e88185610398565b90506103f7602083018461031e565b939250505056fe436865636b696e672076616c75652066726f6d20746c6f6164204646206166746572436865636b696e6720726573756c742063616c6c656520657865637574696f6e206661696c73436865636b696e672076616c75652066726f6d20746c6f6164204645206166746572436865636b696e672076616c75652066726f6d20746c6f6164204645206265666f7265436865636b696e672076616c75652066726f6d20746c6f6164204646206265666f7265a264697066735822122014d79ec53d86680fbb087e64cebf51f7c1e829ea7683527c492cf3316530d26964736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txTstorageDynamicReentrancyContextContract transaction +block_build b01 + parent g00 + transactions txTstorageDynamicReentrancyContextContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txTestReentrantContextRevert transaction +transaction_build txTestReentrantContextRevert + sender acc1 + nonce 1 + contract txTstorageDynamicReentrancyContextContract + value 0 + data 0b35f95c0000000000000000000000000000000000000000000000000000000000000000 + gas 300000 + build + +# Create block to hold txTestReentrantContextRevert transaction +block_build b02 + parent b01 + transactions txTestReentrantContextRevert + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 + +# Create transaction to execute txTestReentrantContextInvalid transaction +transaction_build txTestReentrantContextInvalid transaction + sender acc1 + nonce 2 + contract txTstorageDynamicReentrancyContextContract + value 0 + data 0b35f95c0000000000000000000000000000000000000000000000000000000000000001 + gas 1000000 + build + +# Create block to hold txTestReentrantContextInvalid transaction +block_build b03 + parent b02 + transactions txTestReentrantContextInvalid + gasLimit 1200000 + build + +# Connect block +block_connect b03 + +# Check b03 is best block +assert_best b03 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_reentrancy_context_revert_or_invalid_undoes_tstorage_after_successfull_call.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_reentrancy_context_revert_or_invalid_undoes_tstorage_after_successfull_call.txt new file mode 100644 index 00000000000..75f8a46b6f0 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_reentrancy_context_revert_or_invalid_undoes_tstorage_after_successfull_call.txt @@ -0,0 +1,200 @@ +comment + +// CONTRACT CODE + +pragma solidity ^0.8.24; + +contract TstorageDynamicReentrancyContext { + uint256 reentrantCounter = 0; + uint256 valueLoadedFromFFBefore; + uint256 valueLoadedFromFFAfter; + uint256 resultFirstReentrantCall; + uint256 resultSecondReentrantCall; + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function opcodeUndoesTstorageAfterSuccessfullCall(uint256 opcodeSelector) external { + bytes memory data = abi.encodeWithSignature("opcodeUndoesTstorageAfterSuccessfullCall(uint256)", opcodeSelector); + + assembly { + let reentrantValue := sload(reentrantCounter.slot) + switch reentrantValue + case 1 { + // +1 to the counter so it goes to the other case from reentrant call + reentrantValue := add(reentrantValue, 1) + sstore(reentrantCounter.slot, reentrantValue) + // Switch to select if failure will be caused by opcode revert or invalid opcode + switch opcodeSelector + case 0 { + sstore(resultSecondReentrantCall.slot, call(gas(), address(), 0, add(data, 0x20), mload(data), 0, 0)) + revert(0, 32) + } + case 1 { + sstore(resultSecondReentrantCall.slot, call(0xFFFF, address(), 0, add(data, 0x20), mload(data), 0, 0)) + invalid() + } + } + case 2 { + tstore(0xFF, 0x101) + } + default { + // +1 to the counter so it goes to the other case from reentrant call + reentrantValue := add(reentrantValue, 1) + sstore(reentrantCounter.slot, reentrantValue) + + // Setup the conditions to be tested + tstore(0xFF, 0x100) + sstore(valueLoadedFromFFBefore.slot, tload(0xFF)) + sstore(resultFirstReentrantCall.slot, call(gas(), address(), 0, add(data, 0x20), mload(data), 0, 0)) // saves result from the call so we can check later + sstore(valueLoadedFromFFAfter.slot, tload(0xFF)) + } + } + } + + function checkValuesStoredInTstorage() external { + checkReturnValueExpected(resultFirstReentrantCall, 'Checking result callee execution resultFirstReentrantCall is failed', 0); + checkReturnValueExpected(resultSecondReentrantCall, 'Checking result callee execution resultSecondReentrantCall is failed', 0); + checkReturnValueExpected(valueLoadedFromFFBefore, 'Checking value from tload FF before', 0x100); + checkReturnValueExpected(valueLoadedFromFFAfter, 'Checking value from tload FF after', 0x100); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TstorageDynamicReentrancyContext: 60806040525f8055348015610012575f80fd5b506104de806100205f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80634abdbf22146100385780635f6813d114610054575b5f80fd5b610052600480360381019061004d91906102d1565b61005e565b005b61005c610189565b005b5f81604051602401610070919061030b565b6040516020818303038152906040527f4abdbf22000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f548060018114610131576002811461017c57600182019150815f5561010060ff5d60ff5c6001555f808451602086015f305af160035560ff5c600255610183565b600182019150815f55835f811461014f576001811461016357610176565b5f808551602087015f305af160045560205ffd5b5f808551602087015f3061fffff1600455fe5b50610183565b61010160ff5d5b50505050565b6101ae6003546040518060800160405280604381526020016103ff604391395f610223565b6101d3600454604051806080016040528060448152602001610442604491395f610223565b6101fa60015460405180606001604052806023815260200161048660239139610100610223565b6102216002546040518060600160405280602281526020016103dd60229139610100610223565b565b80830361025b577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610295565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161028c9291906103ae565b60405180910390a15b505050565b5f80fd5b5f819050919050565b6102b08161029e565b81146102ba575f80fd5b50565b5f813590506102cb816102a7565b92915050565b5f602082840312156102e6576102e561029a565b5b5f6102f3848285016102bd565b91505092915050565b6103058161029e565b82525050565b5f60208201905061031e5f8301846102fc565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561035b578082015181840152602081019050610340565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61038082610324565b61038a818561032e565b935061039a81856020860161033e565b6103a381610366565b840191505092915050565b5f6040820190508181035f8301526103c68185610376565b90506103d560208301846102fc565b939250505056fe436865636b696e672076616c75652066726f6d20746c6f6164204646206166746572436865636b696e6720726573756c742063616c6c656520657865637574696f6e20726573756c7446697273745265656e7472616e7443616c6c206973206661696c6564436865636b696e6720726573756c742063616c6c656520657865637574696f6e20726573756c745365636f6e645265656e7472616e7443616c6c206973206661696c6564436865636b696e672076616c75652066726f6d20746c6f6164204646206265666f7265a2646970667358221220ddbb9e72364b1b79e927453462ad5f3aa80de1475c599317f83708e1ef5ca17b64736f6c63430008180033 + +Function hashes + +4abdbf22: opcodeUndoesTstorageAfterSuccessfullCall(uint256) +5f6813d1: checkValuesStoredInTstorage() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstorageDynamicReentrancyContext contract +transaction_build txTstorageDynamicReentrancyContextContract + sender acc1 + receiverAddress 00 + value 0 + data 60806040525f8055348015610012575f80fd5b506104de806100205f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80634abdbf22146100385780635f6813d114610054575b5f80fd5b610052600480360381019061004d91906102d1565b61005e565b005b61005c610189565b005b5f81604051602401610070919061030b565b6040516020818303038152906040527f4abdbf22000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f548060018114610131576002811461017c57600182019150815f5561010060ff5d60ff5c6001555f808451602086015f305af160035560ff5c600255610183565b600182019150815f55835f811461014f576001811461016357610176565b5f808551602087015f305af160045560205ffd5b5f808551602087015f3061fffff1600455fe5b50610183565b61010160ff5d5b50505050565b6101ae6003546040518060800160405280604381526020016103ff604391395f610223565b6101d3600454604051806080016040528060448152602001610442604491395f610223565b6101fa60015460405180606001604052806023815260200161048660239139610100610223565b6102216002546040518060600160405280602281526020016103dd60229139610100610223565b565b80830361025b577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610295565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161028c9291906103ae565b60405180910390a15b505050565b5f80fd5b5f819050919050565b6102b08161029e565b81146102ba575f80fd5b50565b5f813590506102cb816102a7565b92915050565b5f602082840312156102e6576102e561029a565b5b5f6102f3848285016102bd565b91505092915050565b6103058161029e565b82525050565b5f60208201905061031e5f8301846102fc565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561035b578082015181840152602081019050610340565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61038082610324565b61038a818561032e565b935061039a81856020860161033e565b6103a381610366565b840191505092915050565b5f6040820190508181035f8301526103c68185610376565b90506103d560208301846102fc565b939250505056fe436865636b696e672076616c75652066726f6d20746c6f6164204646206166746572436865636b696e6720726573756c742063616c6c656520657865637574696f6e20726573756c7446697273745265656e7472616e7443616c6c206973206661696c6564436865636b696e6720726573756c742063616c6c656520657865637574696f6e20726573756c745365636f6e645265656e7472616e7443616c6c206973206661696c6564436865636b696e672076616c75652066726f6d20746c6f6164204646206265666f7265a2646970667358221220ddbb9e72364b1b79e927453462ad5f3aa80de1475c599317f83708e1ef5ca17b64736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txTstorageDynamicReentrancyContextContract transaction +block_build b01 + parent g00 + transactions txTstorageDynamicReentrancyContextContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txTstoreInDoubleReentrantCallWithRevert transaction +transaction_build txTstoreInDoubleReentrantCallWithRevert + sender acc1 + nonce 1 + contract txTstorageDynamicReentrancyContextContract + value 0 + data 4abdbf220000000000000000000000000000000000000000000000000000000000000000 + gas 300000 + build + +# Create block to hold txTstoreInDoubleReentrantCallWithRevert transaction +block_build b02 + parent b01 + transactions txTstoreInDoubleReentrantCallWithRevert + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 + +# Create transaction to execute txCheckValuesStoredInTstorageForRevert transaction +transaction_build txCheckValuesStoredInTstorageForRevert transaction + sender acc1 + nonce 2 + contract txTstorageDynamicReentrancyContextContract + value 0 + data 5f6813d1 + gas 300000 + build + +# Create block to hold txCheckValuesStoredInTstorageForRevert transaction +block_build b03 + parent b02 + transactions txCheckValuesStoredInTstorageForRevert + gasLimit 350000 + build + +# Connect block +block_connect b03 + +# Check b03 is best block +assert_best b03 + +# Create transaction to execute txTstoreInDoubleReentrantCallWithInvalid transaction +transaction_build txTstoreInDoubleReentrantCallWithInvalid + sender acc1 + nonce 3 + contract txTstorageDynamicReentrancyContextContract + value 0 + data 4abdbf220000000000000000000000000000000000000000000000000000000000000001 + gas 300000 + build + +# Create block to hold txTstoreInDoubleReentrantCallWithInvalid transaction +block_build b04 + parent b03 + transactions txTstoreInDoubleReentrantCallWithInvalid + gasLimit 350000 + build + +# Connect block +block_connect b04 + +# Check b04 is best block +assert_best b04 + +# Create transaction to execute txCheckValuesStoredInTstorageForInvalid transaction +transaction_build txCheckValuesStoredInTstorageForInvalid transaction + sender acc1 + nonce 4 + contract txTstorageDynamicReentrancyContextContract + value 0 + data 5f6813d1 + gas 300000 + build + +# Create block to hold txCheckValuesStoredInTstorageForInvalid transaction +block_build b05 + parent b04 + transactions txCheckValuesStoredInTstorageForInvalid + gasLimit 350000 + build + +# Connect block +block_connect b05 + +# Check b05 is best block +assert_best b05 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_reentrancy_context_tstore_before_revert_or_invalid_has_no_effect.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_reentrancy_context_tstore_before_revert_or_invalid_has_no_effect.txt new file mode 100644 index 00000000000..8d784690e49 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/dynamic_reentrancy_context_tstore_before_revert_or_invalid_has_no_effect.txt @@ -0,0 +1,118 @@ +comment + +// CONTRACT CODE + +pragma solidity ^0.8.24; + +contract TstorageDynamicReentrancyContext { + bool reentrant = false; + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function tstoreBeforeOpcodeHasNoEffect(uint256 opcodeSelector) external { + bytes memory data = abi.encodeWithSignature("tstoreBeforeOpcodeHasNoEffect(uint256)", opcodeSelector); + uint256 fail; + uint256 valueLoadedFromFFBefore; + uint256 valueLoadedFromFFAfter; + + assembly { + let reentrantValue := sload(reentrant.slot) + switch reentrantValue + case 0 { + sstore(reentrant.slot, true) + + tstore(0xFF, 0x100) + valueLoadedFromFFBefore := tload(0xFF) + + mstore(0, 2) + switch opcodeSelector + case 0 { + fail := call(gas(), address(), 0, add(data, 0x20), mload(data), 0, 0) + } + case 1 { + fail := call(0xFFFF, address(), 0, add(data, 0x20), mload(data), 0, 0) + } + valueLoadedFromFFAfter := tload(0xFF) + + } + default { + tstore(0xFF, 0x101) + switch opcodeSelector + case 0 { + revert(0, 0) + } + case 1 { + invalid() + } + } + } + checkReturnValueExpected(fail, 'Checking result callee execution fails', 0); + checkReturnValueExpected(valueLoadedFromFFBefore, 'Checking value from tload FF before', 0x100); + checkReturnValueExpected(valueLoadedFromFFAfter, 'Checking value from tload FF after', 0x100); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TstorageDynamicReentrancyContext: 60806040525f805f6101000a81548160ff021916908315150217905550348015610027575f80fd5b50610431806100355f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063902b3cc81461002d575b5f80fd5b61004760048036038101906100429190610285565b610049565b005b5f8160405160240161005b91906102bf565b6040516020818303038152906040527f902b3cc8000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f805f8054805f811461010e5761010160ff5d865f8114610102576001811461010657610108565b5f80fd5bfe5b50610161565b60015f5561010060ff5d60ff5c935060025f52865f811461013657600181146101495761015a565b5f80885160208a015f305af1955061015a565b5f80885160208a015f3061fffff195505b5060ff5c92505b5050610186836040518060600160405280602681526020016103b3602691395f6101d7565b6101ab826040518060600160405280602381526020016103d9602391396101006101d7565b6101d081604051806060016040528060228152602001610391602291396101006101d7565b5050505050565b80830361020f577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610249565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610240929190610362565b60405180910390a15b505050565b5f80fd5b5f819050919050565b61026481610252565b811461026e575f80fd5b50565b5f8135905061027f8161025b565b92915050565b5f6020828403121561029a5761029961024e565b5b5f6102a784828501610271565b91505092915050565b6102b981610252565b82525050565b5f6020820190506102d25f8301846102b0565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561030f5780820151818401526020810190506102f4565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610334826102d8565b61033e81856102e2565b935061034e8185602086016102f2565b6103578161031a565b840191505092915050565b5f6040820190508181035f83015261037a818561032a565b905061038960208301846102b0565b939250505056fe436865636b696e672076616c75652066726f6d20746c6f6164204646206166746572436865636b696e6720726573756c742063616c6c656520657865637574696f6e206661696c73436865636b696e672076616c75652066726f6d20746c6f6164204646206265666f7265a26469706673582212209e3cc9ab852f09a8d8d7e1daa468813b380a77f02875c4641d7e0e9942b30c1464736f6c63430008180033 + +902b3cc8: tstoreBeforeOpcodeHasNoEffect(uint256) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstorageDynamicReentrancyContext contract +transaction_build txTstorageDynamicReentrancyContextContract + sender acc1 + receiverAddress 00 + value 0 + data 60806040525f805f6101000a81548160ff021916908315150217905550348015610027575f80fd5b50610431806100355f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063902b3cc81461002d575b5f80fd5b61004760048036038101906100429190610285565b610049565b005b5f8160405160240161005b91906102bf565b6040516020818303038152906040527f902b3cc8000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f805f8054805f811461010e5761010160ff5d865f8114610102576001811461010657610108565b5f80fd5bfe5b50610161565b60015f5561010060ff5d60ff5c935060025f52865f811461013657600181146101495761015a565b5f80885160208a015f305af1955061015a565b5f80885160208a015f3061fffff195505b5060ff5c92505b5050610186836040518060600160405280602681526020016103b3602691395f6101d7565b6101ab826040518060600160405280602381526020016103d9602391396101006101d7565b6101d081604051806060016040528060228152602001610391602291396101006101d7565b5050505050565b80830361020f577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610249565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610240929190610362565b60405180910390a15b505050565b5f80fd5b5f819050919050565b61026481610252565b811461026e575f80fd5b50565b5f8135905061027f8161025b565b92915050565b5f6020828403121561029a5761029961024e565b5b5f6102a784828501610271565b91505092915050565b6102b981610252565b82525050565b5f6020820190506102d25f8301846102b0565b92915050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561030f5780820151818401526020810190506102f4565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610334826102d8565b61033e81856102e2565b935061034e8185602086016102f2565b6103578161031a565b840191505092915050565b5f6040820190508181035f83015261037a818561032a565b905061038960208301846102b0565b939250505056fe436865636b696e672076616c75652066726f6d20746c6f6164204646206166746572436865636b696e6720726573756c742063616c6c656520657865637574696f6e206661696c73436865636b696e672076616c75652066726f6d20746c6f6164204646206265666f7265a26469706673582212209e3cc9ab852f09a8d8d7e1daa468813b380a77f02875c4641d7e0e9942b30c1464736f6c63430008180033 + gas 1000000 + build + +# Create transaction to execute txTestReentrantContextRevert transaction +transaction_build txTestReentrantContextRevert + sender acc1 + nonce 1 + contract txTstorageDynamicReentrancyContextContract + value 0 + data 902b3cc80000000000000000000000000000000000000000000000000000000000000000 + gas 300000 + build + +# Create transaction to execute txTestReentrantContextInvalid transaction +transaction_build txTestReentrantContextInvalid transaction + sender acc1 + nonce 2 + contract txTstorageDynamicReentrancyContextContract + value 0 + data 902b3cc80000000000000000000000000000000000000000000000000000000000000001 + gas 1000000 + build + +# Create block to hold txTestReentrantContextInvalid transaction +block_build b01 + parent g00 + transactions txTstorageDynamicReentrancyContextContract txTestReentrantContextRevert txTestReentrantContextInvalid + gasLimit 3000000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/eip1153_basic_tests.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/eip1153_basic_tests.txt new file mode 100644 index 00000000000..ab650a093bb --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/eip1153_basic_tests.txt @@ -0,0 +1,223 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TestsTransientStorageEip1153BasicScenarios { + bytes32[] slotsToTest = new bytes32[](4); + + constructor() { + slotsToTest[0] = 0x0000000000000000000000000000000000000000000000000000000000000001; + slotsToTest[1] = 0x0000000000000000000000000000000000000000000000000000000000000002; + slotsToTest[2] = 0x0000000000000000000000000000000100000000000000000000000000000000; + slotsToTest[3] = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + } + + event OK(); + event ERROR(bytes32); + + // Test that loading an arbitrary value is 0 at beginning of transaction: TLOAD(x) is 0 + function testTransientUnsetValues() external { + bytes32 valueLoaded; + for (uint i = 0; i < slotsToTest.length; i++) { + bytes32 currentSlot = slotsToTest[i]; + assembly { + valueLoaded := tload(currentSlot) + } + if (valueLoaded == 0x0) { + emit OK(); + } else { + emit ERROR(valueLoaded); + } + } + } + + // Test that Loading after storing returns the stored value: TSTORE(x, y), TLOAD(x) returns y + function testTloadAfterTstore() external { + bytes32 valueLoaded; + for (uint i = 0; i < slotsToTest.length; i++) { + bytes32 currentSlot = slotsToTest[i]; + assembly { + tstore(currentSlot, currentSlot) + valueLoaded := tload(currentSlot) + } + if (valueLoaded == currentSlot) { + emit OK(); + } else { + emit ERROR(valueLoaded); + } + } + } + + // Transient loading after storing does not return the stored value: STORE(x, y), TLOAD(x) returns 0 + function testTloadAfterSstore() external { + bytes32 valueLoaded; + for (uint i = 0; i < slotsToTest.length; i++) { + bytes32 currentSlot = slotsToTest[i]; + assembly { + sstore(currentSlot, 0xFF) + valueLoaded := tload(currentSlot) + } + if (valueLoaded == 0x0) { + emit OK(); + } else { + emit ERROR(valueLoaded); + } + } + } + + // Transient loading after storing does not return the stored value: STORE(x, y), TLOAD(x) returns 0 + function testTloadAfterTstoreIsZero() external { + bytes32 valueLoaded; + bytes32[] memory slotsDifferentKeys = new bytes32[](4); + slotsDifferentKeys[0] = 0x0000000000000000000000000000000000000000000000000000000000000003; + slotsDifferentKeys[1] = 0x0000000000000000000000000000000000000000000000000000000000000004; + slotsDifferentKeys[2] = 0x0000000000000000000000000000000100000000000000000000000000000001; + slotsDifferentKeys[3] = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe; + for (uint i = 0; i < slotsToTest.length; i++) { + bytes32 currentSlot = slotsToTest[i]; + bytes32 currentSlotDifferent = slotsDifferentKeys[i]; + assembly { + tstore(currentSlot, 0x4D2) + valueLoaded := tload(currentSlotDifferent) + } + if (valueLoaded == 0x0) { + emit OK(); + } else { + emit ERROR(valueLoaded); + } + } + } +} + +// CONTRACT BYTECODE + +TestsTransientStorageEip1153BasicScenarios: 6080604052600467ffffffffffffffff81111561001f5761001e610198565b5b60405190808252806020026020018201604052801561004d5781602001602082028036833780820191505090505b505f9080519060200190610062929190610132565b5034801561006e575f80fd5b5060015f1b5f8081548110610086576100856101c5565b5b905f5260205f20018190555060025f1b5f6001815481106100aa576100a96101c5565b5b905f5260205f2001819055507001000000000000000000000000000000005f1b5f6002815481106100de576100dd6101c5565b5b905f5260205f2001819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f1b5f600381548110610121576101206101c5565b5b905f5260205f2001819055506101f2565b828054828255905f5260205f2090810192821561016c579160200282015b8281111561016b578251825591602001919060010190610150565b5b509050610179919061017d565b5090565b5b80821115610194575f815f90555060010161017e565b5090565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b61054d806101ff5f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c806308cf7e911461004e5780633ba13899146100585780634f3f02ee14610062578063d0519a7f1461006c575b5f80fd5b610056610076565b005b610060610130565b005b61006a610316565b005b6100746103cf565b005b5f805f90505b5f8054905081101561012c575f80828154811061009c5761009b61048c565b5b905f5260205f200154905080815d805c92508083036100e6577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161011e565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd98360405161011591906104d1565b60405180910390a15b50808060010191505061007c565b5050565b5f80600467ffffffffffffffff81111561014d5761014c6104ea565b5b60405190808252806020026020018201604052801561017b5781602001602082028036833780820191505090505b50905060035f1b815f815181106101955761019461048c565b5b60200260200101818152505060045f1b816001815181106101b9576101b861048c565b5b6020026020010181815250507001000000000000000000000000000000015f1b816002815181106101ed576101ec61048c565b5b6020026020010181815250507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe5f1b816003815181106102305761022f61048c565b5b6020026020010181815250505f5b5f80549050811015610311575f80828154811061025e5761025d61048c565b5b905f5260205f20015490505f83838151811061027d5761027c61048c565b5b602002602001015190506104d2825d805c94505f801b85036102ca577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610302565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9856040516102f991906104d1565b60405180910390a15b5050808060010191505061023e565b505050565b5f805f90505b5f805490508110156103cb575f80828154811061033c5761033b61048c565b5b905f5260205f2001549050805c92505f801b8303610385577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16103bd565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9836040516103b491906104d1565b60405180910390a15b50808060010191505061031c565b5050565b5f805f90505b5f80549050811015610488575f8082815481106103f5576103f461048c565b5b905f5260205f200154905060ff8155805c92505f801b8303610442577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161047a565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd98360405161047191906104d1565b60405180910390a15b5080806001019150506103d5565b5050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b6104cb816104b9565b82525050565b5f6020820190506104e45f8301846104c2565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffdfea26469706673582212204bf46b78c1fcafe2ef7b46d0b4632777b5d37316aed745194ce7eac231a4f4c464736f6c634300081a0033 + +// CONTRACT CALLS + +TestsTransientStorageEip1153BasicScenarios: + + - d0519a7f: testTloadAfterSstore() + - 08cf7e91: testTloadAfterTstore() + - 4f3f02ee: testTransientUnsetValues() + - 3ba13899: testTloadAfterTstoreIsZero() + +end + + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorage contract +transaction_build txTestTransientStorageContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052600467ffffffffffffffff81111561001f5761001e610198565b5b60405190808252806020026020018201604052801561004d5781602001602082028036833780820191505090505b505f9080519060200190610062929190610132565b5034801561006e575f80fd5b5060015f1b5f8081548110610086576100856101c5565b5b905f5260205f20018190555060025f1b5f6001815481106100aa576100a96101c5565b5b905f5260205f2001819055507001000000000000000000000000000000005f1b5f6002815481106100de576100dd6101c5565b5b905f5260205f2001819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f1b5f600381548110610121576101206101c5565b5b905f5260205f2001819055506101f2565b828054828255905f5260205f2090810192821561016c579160200282015b8281111561016b578251825591602001919060010190610150565b5b509050610179919061017d565b5090565b5b80821115610194575f815f90555060010161017e565b5090565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b61054d806101ff5f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c806308cf7e911461004e5780633ba13899146100585780634f3f02ee14610062578063d0519a7f1461006c575b5f80fd5b610056610076565b005b610060610130565b005b61006a610316565b005b6100746103cf565b005b5f805f90505b5f8054905081101561012c575f80828154811061009c5761009b61048c565b5b905f5260205f200154905080815d805c92508083036100e6577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161011e565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd98360405161011591906104d1565b60405180910390a15b50808060010191505061007c565b5050565b5f80600467ffffffffffffffff81111561014d5761014c6104ea565b5b60405190808252806020026020018201604052801561017b5781602001602082028036833780820191505090505b50905060035f1b815f815181106101955761019461048c565b5b60200260200101818152505060045f1b816001815181106101b9576101b861048c565b5b6020026020010181815250507001000000000000000000000000000000015f1b816002815181106101ed576101ec61048c565b5b6020026020010181815250507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe5f1b816003815181106102305761022f61048c565b5b6020026020010181815250505f5b5f80549050811015610311575f80828154811061025e5761025d61048c565b5b905f5260205f20015490505f83838151811061027d5761027c61048c565b5b602002602001015190506104d2825d805c94505f801b85036102ca577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610302565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9856040516102f991906104d1565b60405180910390a15b5050808060010191505061023e565b505050565b5f805f90505b5f805490508110156103cb575f80828154811061033c5761033b61048c565b5b905f5260205f2001549050805c92505f801b8303610385577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16103bd565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9836040516103b491906104d1565b60405180910390a15b50808060010191505061031c565b5050565b5f805f90505b5f80549050811015610488575f8082815481106103f5576103f461048c565b5b905f5260205f200154905060ff8155805c92505f801b8303610442577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161047a565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd98360405161047191906104d1565b60405180910390a15b5080806001019150506103d5565b5050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b6104cb816104b9565b82525050565b5f6020820190506104e45f8301846104c2565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffdfea26469706673582212204bf46b78c1fcafe2ef7b46d0b4632777b5d37316aed745194ce7eac231a4f4c464736f6c634300081a0033 + gas 1000000 + build + +# Create block to hold txTestTransientStorageContract transaction +block_build b01 + parent g00 + transactions txTestTransientStorageContract + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute +transaction_build txTestTloadAfterSstore + sender acc1 + nonce 1 + contract txTestTransientStorageContract + value 0 + data d0519a7f + gas 200000 + build + +# Create block to hold TloadAfterSstore transaction +block_build b02 + parent b01 + transactions txTestTloadAfterSstore + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 + +# Create transaction to execute +transaction_build txTestTloadAfterTstore + sender acc1 + nonce 2 + contract txTestTransientStorageContract + value 0 + data 08cf7e91 + gas 200000 + build + +# Create block to hold txTest transaction +block_build b03 + parent b02 + transactions txTestTloadAfterTstore + gasLimit 350000 + build + +# Connect block +block_connect b03 + +# Check b03 is best block +assert_best b03 + +# Create transaction to execute +transaction_build txTestTransientUnsetValues + sender acc1 + nonce 3 + contract txTestTransientStorageContract + value 0 + data 4f3f02ee + gas 200000 + build + +# Create block to hold txTestTransientUnsetValues transaction +block_build b04 + parent b03 + transactions txTestTransientUnsetValues + gasLimit 350000 + build + +# Connect block +block_connect b04 + +# Check b04 is best block +assert_best b04 + +# Create transaction to execute +transaction_build txTestTloadAfterTstoreIsZero + sender acc1 + nonce 4 + contract txTestTransientStorageContract + value 0 + data 3ba13899 + gas 200000 + build + +# Create block to hold txTestTloadAfterTstoreIsZero transaction +block_build b05 + parent b04 + transactions txTestTloadAfterTstoreIsZero + gasLimit 350000 + build + +# Connect block +block_connect b05 + +# Check b05 is best block +assert_best b05 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/in_constructor_and_deploy_code_create_context.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/in_constructor_and_deploy_code_create_context.txt new file mode 100644 index 00000000000..e8d276915bb --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/in_constructor_and_deploy_code_create_context.txt @@ -0,0 +1,129 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract InConstructorAndCode { + + constructor() { + bytes32 valueLoadedInitially; + assembly{ + valueLoadedInitially := tload(0) + } + checkReturnValueExpected(valueLoadedInitially, 'Checking value loaded in 0 from creator is inacessible in constructor', 0x00); + } + + event OK(); + event ERROR(string, bytes32); + + function deployedCode() external { + bytes32 valueLoadedInitially; + bytes32 valueLoadedAfterStore; + assembly{ + valueLoadedInitially := tload(0) + tstore(1,0x0000000000000000000000000000000100000000000000000000000000000001) + valueLoadedAfterStore := tload(1) + } + checkReturnValueExpected(valueLoadedInitially, 'Checking value loaded in 0 from creator is inacessible in deployed code', 0x00); + checkReturnValueExpected(valueLoadedAfterStore, 'Checking value stored in 1 from deployed is accessible', 0x0000000000000000000000000000000100000000000000000000000000000001); + } + + + function checkReturnValueExpected(bytes32 valueReceived, string memory message, bytes32 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract TestStorageCreateContexts { + constructor(){ + } + + event OK(); + event ERROR(string, bytes32); + + function testInConstructorAndCode() external { + configureTransientStorageFromCaller(); + InConstructorAndCode testContract = new InConstructorAndCode(); + testContract.deployedCode(); + checkTransientStorageFromCaller(); + } + + function configureTransientStorageFromCaller() private { + assembly{ + tstore(0, 0x0000000000000000000000000000000000000000000000000000000000000002) + tstore(1, 0x0000000000000000000000000000000000000000000000000000000000000003) + tstore(2, 0x0000000000000000000000000000000000000000000000000000000000000004) + calldatacopy(0, 0, calldatasize()) + } + } + + function checkTransientStorageFromCaller() private { + bytes32 valueIn0Received; + bytes32 valueIn1Received; + bytes32 valueIn2Received; + + assembly{ + valueIn0Received := tload(0) + valueIn1Received := tload(1) + valueIn2Received := tload(2) + } + checkReturnValueExpected(valueIn0Received, 'Checking value in 0', 0x0000000000000000000000000000000000000000000000000000000000000002); + checkReturnValueExpected(valueIn1Received, 'Checking value in 1', 0x0000000000000000000000000000000000000000000000000000000000000003); + checkReturnValueExpected(valueIn2Received, 'Checking value in 2', 0x0000000000000000000000000000000000000000000000000000000000000004); + } + + function checkReturnValueExpected(bytes32 valueReceived, string memory message, bytes32 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TestStorageCreateContexts: 6080604052348015600e575f80fd5b5061078c8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c806324182ad51461002d575b5f80fd5b610035610037565b005b61003f6100ce565b5f60405161004c90610238565b604051809103905ff080158015610065573d5f803e3d5ffd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663a45449eb6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156100ad575f80fd5b505af11580156100bf573d5f803e3d5ffd5b505050506100cb6100e2565b50565b60025f5d600360015d600460025d365f8037565b5f805f805c925060015c915060025c9050610136836040518060400160405280601381526020017f436865636b696e672076616c756520696e20300000000000000000000000000081525060025f1b6101c1565b610179826040518060400160405280601381526020017f436865636b696e672076616c756520696e20310000000000000000000000000081525060035f1b6101c1565b6101bc816040518060400160405280601381526020017f436865636b696e672076616c756520696e20320000000000000000000000000081525060045f1b6101c1565b505050565b8083036101f9577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610233565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161022a9291906102cd565b60405180910390a15b505050565b61045b806102fc83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61028782610245565b610291818561024f565b93506102a181856020860161025f565b6102aa8161026d565b840191505092915050565b5f819050919050565b6102c7816102b5565b82525050565b5f6040820190508181035f8301526102e5818561027d565b90506102f460208301846102be565b939250505056fe608060405234801561000f575f80fd5b505f805c905061004081604051806080016040528060458152602001610416604591395f801b61004660201b60201c565b50610173565b80830361007e577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100b8565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd382846040516100af929190610145565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6100ff826100bd565b61010981856100c7565b93506101198185602086016100d7565b610122816100e5565b840191505092915050565b5f819050919050565b61013f8161012d565b82525050565b5f6040820190508181035f83015261015d81856100f5565b905061016c6020830184610136565b9392505050565b610296806101805f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063a45449eb1461002d575b5f80fd5b610035610037565b005b5f805f5c915070010000000000000000000000000000000160015d60015c905061007c826040518060800160405280604781526020016101e4604791395f801b6100b6565b6100b28160405180606001604052806036815260200161022b603691397001000000000000000000000000000000015f1b6100b6565b5050565b8083036100ee577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610128565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161011f9291906101b5565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61016f8261012d565b6101798185610137565b9350610189818560208601610147565b61019281610155565b840191505092915050565b5f819050919050565b6101af8161019d565b82525050565b5f6040820190508181035f8301526101cd8185610165565b90506101dc60208301846101a6565b939250505056fe436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c6520696e206465706c6f79656420636f6465436865636b696e672076616c75652073746f72656420696e20312066726f6d206465706c6f7965642069732061636365737369626c65a26469706673582212204ceee425512f119ce702deae18164eee3232e3d3df3030b9259ae7cf48cce05d64736f6c634300081a0033436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c6520696e20636f6e7374727563746f72a26469706673582212201a9e5334b9d41459e465fb8c2d62cd42e734141dc331c5944ff8be6dcae694e764736f6c634300081a0033 + +24182ad5: testInConstructorAndCode() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCreateContextsContract contract +transaction_build txTestTransientStorageCreateContextsContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f80fd5b5061078c8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c806324182ad51461002d575b5f80fd5b610035610037565b005b61003f6100ce565b5f60405161004c90610238565b604051809103905ff080158015610065573d5f803e3d5ffd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663a45449eb6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156100ad575f80fd5b505af11580156100bf573d5f803e3d5ffd5b505050506100cb6100e2565b50565b60025f5d600360015d600460025d365f8037565b5f805f805c925060015c915060025c9050610136836040518060400160405280601381526020017f436865636b696e672076616c756520696e20300000000000000000000000000081525060025f1b6101c1565b610179826040518060400160405280601381526020017f436865636b696e672076616c756520696e20310000000000000000000000000081525060035f1b6101c1565b6101bc816040518060400160405280601381526020017f436865636b696e672076616c756520696e20320000000000000000000000000081525060045f1b6101c1565b505050565b8083036101f9577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610233565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161022a9291906102cd565b60405180910390a15b505050565b61045b806102fc83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61028782610245565b610291818561024f565b93506102a181856020860161025f565b6102aa8161026d565b840191505092915050565b5f819050919050565b6102c7816102b5565b82525050565b5f6040820190508181035f8301526102e5818561027d565b90506102f460208301846102be565b939250505056fe608060405234801561000f575f80fd5b505f805c905061004081604051806080016040528060458152602001610416604591395f801b61004660201b60201c565b50610173565b80830361007e577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100b8565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd382846040516100af929190610145565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6100ff826100bd565b61010981856100c7565b93506101198185602086016100d7565b610122816100e5565b840191505092915050565b5f819050919050565b61013f8161012d565b82525050565b5f6040820190508181035f83015261015d81856100f5565b905061016c6020830184610136565b9392505050565b610296806101805f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063a45449eb1461002d575b5f80fd5b610035610037565b005b5f805f5c915070010000000000000000000000000000000160015d60015c905061007c826040518060800160405280604781526020016101e4604791395f801b6100b6565b6100b28160405180606001604052806036815260200161022b603691397001000000000000000000000000000000015f1b6100b6565b5050565b8083036100ee577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610128565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161011f9291906101b5565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61016f8261012d565b6101798185610137565b9350610189818560208601610147565b61019281610155565b840191505092915050565b5f819050919050565b6101af8161019d565b82525050565b5f6040820190508181035f8301526101cd8185610165565b90506101dc60208301846101a6565b939250505056fe436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c6520696e206465706c6f79656420636f6465436865636b696e672076616c75652073746f72656420696e20312066726f6d206465706c6f7965642069732061636365737369626c65a26469706673582212204ceee425512f119ce702deae18164eee3232e3d3df3030b9259ae7cf48cce05d64736f6c634300081a0033436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c6520696e20636f6e7374727563746f72a26469706673582212201a9e5334b9d41459e465fb8c2d62cd42e734141dc331c5944ff8be6dcae694e764736f6c634300081a0033 + gas 1000000 + build + +# Create transaction to execute txInConstructorAndCode transaction +transaction_build txInConstructorAndCode + sender acc1 + nonce 1 + contract txTestTransientStorageCreateContextsContract + value 0 + data 24182ad5 + gas 1000000 + build + +# Create block to hold txInConstructorAndCode transaction +block_build b01 + parent g00 + transactions txTestTransientStorageCreateContextsContract txInConstructorAndCode + gasLimit 3000000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/no_constructor_code_create_context.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/no_constructor_code_create_context.txt new file mode 100644 index 00000000000..80b69f93731 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/no_constructor_code_create_context.txt @@ -0,0 +1,137 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract NoConstructorCode { + + constructor() { + } + + event OK(); + event ERROR(string, bytes32); + + function deployedCode() external { + bytes32 valueLoadedInitially; + bytes32 valueLoadedAfterStore; + assembly{ + valueLoadedInitially := tload(0) + tstore(1, 0x0000000000000000000000000000000000000000000000000000000000000555) + valueLoadedAfterStore := tload(1) + } + checkReturnValueExpected(valueLoadedInitially, 'Checking value loaded in 0 from creator is inacessible in deployed code', 0x00); + checkReturnValueExpected(valueLoadedAfterStore, 'Checking value stored in 1 from deployed is accessible', 0x0000000000000000000000000000000000000000000000000000000000000555); + } + + + function checkReturnValueExpected(bytes32 valueReceived, string memory message, bytes32 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract TestStorageCreateContexts { + constructor(){ + } + + event OK(); + event ERROR(string, bytes32); + + function testNoConstructorCode() external { + configureTransientStorageFromCaller(); + NoConstructorCode testContract = new NoConstructorCode(); + testContract.deployedCode(); + checkTransientStorageFromCaller(); + } + + function configureTransientStorageFromCaller() private { + assembly{ + tstore(0, 0x0000000000000000000000000000000000000000000000000000000000000002) + tstore(1, 0x0000000000000000000000000000000000000000000000000000000000000003) + tstore(2, 0x0000000000000000000000000000000000000000000000000000000000000004) + calldatacopy(0, 0, calldatasize()) + } + } + + function checkTransientStorageFromCaller() private { + bytes32 valueIn0Received; + bytes32 valueIn1Received; + bytes32 valueIn2Received; + + assembly{ + valueIn0Received := tload(0) + valueIn1Received := tload(1) + valueIn2Received := tload(2) + } + checkReturnValueExpected(valueIn0Received, 'Checking value in 0', 0x0000000000000000000000000000000000000000000000000000000000000002); + checkReturnValueExpected(valueIn1Received, 'Checking value in 1', 0x0000000000000000000000000000000000000000000000000000000000000003); + checkReturnValueExpected(valueIn2Received, 'Checking value in 2', 0x0000000000000000000000000000000000000000000000000000000000000004); + } + + function checkReturnValueExpected(bytes32 valueReceived, string memory message, bytes32 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TestStorageCreateContexts: 6080604052348015600e575f80fd5b506105c58061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063aeb8338c1461002d575b5f80fd5b610035610037565b005b61003f6100ce565b5f60405161004c90610238565b604051809103905ff080158015610065573d5f803e3d5ffd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663a45449eb6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156100ad575f80fd5b505af11580156100bf573d5f803e3d5ffd5b505050506100cb6100e2565b50565b60025f5d600360015d600460025d365f8037565b5f805f805c925060015c915060025c9050610136836040518060400160405280601381526020017f436865636b696e672076616c756520696e20300000000000000000000000000081525060025f1b6101c1565b610179826040518060400160405280601381526020017f436865636b696e672076616c756520696e20310000000000000000000000000081525060035f1b6101c1565b6101bc816040518060400160405280601381526020017f436865636b696e672076616c756520696e20320000000000000000000000000081525060045f1b6101c1565b505050565b8083036101f9577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610233565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161022a9291906102cd565b60405180910390a15b505050565b610294806102fc83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61028782610245565b610291818561024f565b93506102a181856020860161025f565b6102aa8161026d565b840191505092915050565b5f819050919050565b6102c7816102b5565b82525050565b5f6040820190508181035f8301526102e5818561027d565b90506102f460208301846102be565b939250505056fe6080604052348015600e575f80fd5b506102788061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063a45449eb1461002d575b5f80fd5b610035610037565b005b5f805f5c915061055560015d60015c905061006d826040518060800160405280604781526020016101c6604791395f801b610098565b6100948160405180606001604052806036815260200161020d603691396105555f1b610098565b5050565b8083036100d0577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161010a565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd38284604051610101929190610197565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6101518261010f565b61015b8185610119565b935061016b818560208601610129565b61017481610137565b840191505092915050565b5f819050919050565b6101918161017f565b82525050565b5f6040820190508181035f8301526101af8185610147565b90506101be6020830184610188565b939250505056fe436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c6520696e206465706c6f79656420636f6465436865636b696e672076616c75652073746f72656420696e20312066726f6d206465706c6f7965642069732061636365737369626c65a26469706673582212207a7362f3095add92a0a854cee8d39f155bec093d65abc358095a3c70c8517c3164736f6c634300081a0033a2646970667358221220f92680fe2ad24e88124b423703506fbb1ee4964eebdc02acdfe21bb7b036a13c64736f6c634300081a0033 + +06c31e01: testNoConstructorCode() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCreateContextsContract contract +transaction_build txTestTransientStorageCreateContextsContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f80fd5b506105c58061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063aeb8338c1461002d575b5f80fd5b610035610037565b005b61003f6100ce565b5f60405161004c90610238565b604051809103905ff080158015610065573d5f803e3d5ffd5b5090508073ffffffffffffffffffffffffffffffffffffffff1663a45449eb6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156100ad575f80fd5b505af11580156100bf573d5f803e3d5ffd5b505050506100cb6100e2565b50565b60025f5d600360015d600460025d365f8037565b5f805f805c925060015c915060025c9050610136836040518060400160405280601381526020017f436865636b696e672076616c756520696e20300000000000000000000000000081525060025f1b6101c1565b610179826040518060400160405280601381526020017f436865636b696e672076616c756520696e20310000000000000000000000000081525060035f1b6101c1565b6101bc816040518060400160405280601381526020017f436865636b696e672076616c756520696e20320000000000000000000000000081525060045f1b6101c1565b505050565b8083036101f9577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610233565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd3828460405161022a9291906102cd565b60405180910390a15b505050565b610294806102fc83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61028782610245565b610291818561024f565b93506102a181856020860161025f565b6102aa8161026d565b840191505092915050565b5f819050919050565b6102c7816102b5565b82525050565b5f6040820190508181035f8301526102e5818561027d565b90506102f460208301846102be565b939250505056fe6080604052348015600e575f80fd5b506102788061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063a45449eb1461002d575b5f80fd5b610035610037565b005b5f805f5c915061055560015d60015c905061006d826040518060800160405280604781526020016101c6604791395f801b610098565b6100948160405180606001604052806036815260200161020d603691396105555f1b610098565b5050565b8083036100d0577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161010a565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd38284604051610101929190610197565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6101518261010f565b61015b8185610119565b935061016b818560208601610129565b61017481610137565b840191505092915050565b5f819050919050565b6101918161017f565b82525050565b5f6040820190508181035f8301526101af8185610147565b90506101be6020830184610188565b939250505056fe436865636b696e672076616c7565206c6f6164656420696e20302066726f6d2063726561746f7220697320696e616365737369626c6520696e206465706c6f79656420636f6465436865636b696e672076616c75652073746f72656420696e20312066726f6d206465706c6f7965642069732061636365737369626c65a26469706673582212207a7362f3095add92a0a854cee8d39f155bec093d65abc358095a3c70c8517c3164736f6c634300081a0033a2646970667358221220f92680fe2ad24e88124b423703506fbb1ee4964eebdc02acdfe21bb7b036a13c64736f6c634300081a0033 + gas 1000000 + build + +# Create block to hold txTestTransientStorageCreateContextsContract transaction +block_build b01 + parent g00 + transactions txTestTransientStorageCreateContextsContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txNoConstructorCode transaction +transaction_build txNoConstructorCode + sender acc1 + nonce 1 + contract txTestTransientStorageCreateContextsContract + value 0 + data aeb8338c + gas 1000000 + build + +# Create block to hold txNoConstructorCode transaction +block_build b02 + parent b01 + transactions txNoConstructorCode + gasLimit 2000000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/only_constructor_code_create_context.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/only_constructor_code_create_context.txt new file mode 100644 index 00000000000..a4b4dc88923 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/only_constructor_code_create_context.txt @@ -0,0 +1,133 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract OnlyConstructorCode { + + constructor() { + bytes32 valueLoadedInitially; + bytes32 valueLoadedAfterStore; + assembly{ + valueLoadedInitially := tload(0) + tstore(1, 0x0000000000000000000000000000000000000000000000000000000000000002) + valueLoadedAfterStore := tload(1) + } + if(valueLoadedInitially == 0x0000){ + emit OK(); + } else { + emit ERROR(valueLoadedInitially); + } + + if(valueLoadedAfterStore == 0x0000000000000000000000000000000000000000000000000000000000000002){ + emit OK(); + } else { + emit ERROR(valueLoadedAfterStore); + } + } + + event OK(); + event ERROR(bytes32); +} + +contract TestStorageCreateContexts { + constructor(){ + } + + event OK(); + event ERROR(string, bytes32); + + function testOnlyConstructorCode() external { + configureTransientStorageFromCaller(); + new OnlyConstructorCode(); + checkTransientStorageFromCaller(); + } + + function configureTransientStorageFromCaller() private { + assembly{ + tstore(0, 0x0000000000000000000000000000000000000000000000000000000000000002) + tstore(1, 0x0000000000000000000000000000000000000000000000000000000000000003) + tstore(2, 0x0000000000000000000000000000000000000000000000000000000000000004) + calldatacopy(0, 0, calldatasize()) + } + } + + function checkTransientStorageFromCaller() private { + bytes32 valueIn0Received; + bytes32 valueIn1Received; + bytes32 valueIn2Received; + + assembly{ + valueIn0Received := tload(0) + valueIn1Received := tload(1) + valueIn2Received := tload(2) + } + checkReturnValueExpected(valueIn0Received, 'Checking value in 0', 0x0000000000000000000000000000000000000000000000000000000000000002); + checkReturnValueExpected(valueIn1Received, 'Checking value in 1', 0x0000000000000000000000000000000000000000000000000000000000000003); + checkReturnValueExpected(valueIn2Received, 'Checking value in 2', 0x0000000000000000000000000000000000000000000000000000000000000004); + } + + function checkReturnValueExpected(bytes32 valueReceived, string memory message, bytes32 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TestStorageCreateContexts: 6080604052348015600e575f80fd5b5061045a8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c806306c31e011461002d575b5f80fd5b610035610037565b005b61003f610070565b60405161004b906101da565b604051809103905ff080158015610064573d5f803e3d5ffd5b505061006e610084565b565b60025f5d600360015d600460025d365f8037565b5f805f805c925060015c915060025c90506100d8836040518060400160405280601381526020017f436865636b696e672076616c756520696e20300000000000000000000000000081525060025f1b610163565b61011b826040518060400160405280601381526020017f436865636b696e672076616c756520696e20310000000000000000000000000081525060035f1b610163565b61015e816040518060400160405280601381526020017f436865636b696e672076616c756520696e20320000000000000000000000000081525060045f1b610163565b505050565b80830361019b577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101d5565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd382846040516101cc92919061026f565b60405180910390a15b505050565b6101878061029e83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610229826101e7565b61023381856101f1565b9350610243818560208601610201565b61024c8161020f565b840191505092915050565b5f819050919050565b61026981610257565b82525050565b5f6040820190508181035f830152610287818561021f565b90506102966020830184610260565b939250505056fe608060405234801561000f575f80fd5b505f805f5c9150600260015d60015c90505f801b820361005a577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610092565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9826040516100899190610124565b60405180910390a15b60025f1b81036100cd577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610105565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9816040516100fc9190610124565b60405180910390a15b505061013d565b5f819050919050565b61011e8161010c565b82525050565b5f6020820190506101375f830184610115565b92915050565b603e806101495f395ff3fe60806040525f80fdfea26469706673582212208c7f41dc7ce3e60c1ac6a8857d261787c82e80556c6e9301ddc90b0332365ae764736f6c634300081a0033a2646970667358221220dd0d78a91f17116a6d00e03e0496b3200f5de2bc835011e5943baa5b8dab956e64736f6c634300081a0033 + +06c31e01: testOnlyConstructorCode() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorageCreateContextsContract contract +transaction_build txTestTransientStorageCreateContextsContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f80fd5b5061045a8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c806306c31e011461002d575b5f80fd5b610035610037565b005b61003f610070565b60405161004b906101da565b604051809103905ff080158015610064573d5f803e3d5ffd5b505061006e610084565b565b60025f5d600360015d600460025d365f8037565b5f805f805c925060015c915060025c90506100d8836040518060400160405280601381526020017f436865636b696e672076616c756520696e20300000000000000000000000000081525060025f1b610163565b61011b826040518060400160405280601381526020017f436865636b696e672076616c756520696e20310000000000000000000000000081525060035f1b610163565b61015e816040518060400160405280601381526020017f436865636b696e672076616c756520696e20320000000000000000000000000081525060045f1b610163565b505050565b80830361019b577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101d5565b7f76846b797b13411b14ef41db4387da9918f2f43457c5528a2423c48d45704bd382846040516101cc92919061026f565b60405180910390a15b505050565b6101878061029e83390190565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f610229826101e7565b61023381856101f1565b9350610243818560208601610201565b61024c8161020f565b840191505092915050565b5f819050919050565b61026981610257565b82525050565b5f6040820190508181035f830152610287818561021f565b90506102966020830184610260565b939250505056fe608060405234801561000f575f80fd5b505f805f5c9150600260015d60015c90505f801b820361005a577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610092565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9826040516100899190610124565b60405180910390a15b60025f1b81036100cd577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610105565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9816040516100fc9190610124565b60405180910390a15b505061013d565b5f819050919050565b61011e8161010c565b82525050565b5f6020820190506101375f830184610115565b92915050565b603e806101495f395ff3fe60806040525f80fdfea26469706673582212208c7f41dc7ce3e60c1ac6a8857d261787c82e80556c6e9301ddc90b0332365ae764736f6c634300081a0033a2646970667358221220dd0d78a91f17116a6d00e03e0496b3200f5de2bc835011e5943baa5b8dab956e64736f6c634300081a0033 + gas 1000000 + build + +# Create block to hold txTestTransientStorageCreateContextsContract transaction +block_build b01 + parent g00 + transactions txTestTransientStorageCreateContextsContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txOnlyConstructorCode transaction +transaction_build txOnlyConstructorCode + sender acc1 + nonce 1 + contract txTestTransientStorageCreateContextsContract + value 0 + data 06c31e01 + gas 1000000 + build + +# Create block to hold txOnlyConstructorCode transaction +block_build b02 + parent b01 + transactions txOnlyConstructorCode + gasLimit 1200000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_manipulate_in_reentrant_call.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_manipulate_in_reentrant_call.txt new file mode 100644 index 00000000000..8cc99938734 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_manipulate_in_reentrant_call.txt @@ -0,0 +1,136 @@ +comment + +// CONTRACT CODE + +pragma solidity ^0.8.24; + +contract TstorageReentrancyContextTest { + bool reentrant = false; + uint256 success; + uint256 valueLoadedAfterSubcall; + uint256 valueLoadedBeforeSubcall; + uint256 valueLoadedInSubcall; + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function manipulateInReentrantCall() external { + bytes memory data = abi.encodeWithSignature("manipulateInReentrantCall()"); + + assembly { + let reentrantValue := sload(reentrant.slot) + switch reentrantValue + case 0 { + sstore(reentrant.slot, true) + + tstore(0xFF, 0x100) + sstore(valueLoadedBeforeSubcall.slot, tload(0xFF)) + mstore(0, 2) + sstore(success.slot, call(gas(), address(), 0, add(data, 0x20), mload(data), 0, 0)) + sstore(valueLoadedAfterSubcall.slot, tload(0xFF)) + } + default { + tstore(0xFF, 0x101) + sstore(valueLoadedInSubcall.slot, tload(0xFF)) + } + } + } + + function checkValuesStoredInTstorage() external { + checkReturnValueExpected(valueLoadedBeforeSubcall, 'Checking value from tload before subcall', 0x100); + checkReturnValueExpected(success, 'Checking result callee execution is with success', 1); + checkReturnValueExpected(valueLoadedInSubcall, 'Checking value from tload inside subcall', 0x101); + checkReturnValueExpected(valueLoadedAfterSubcall, 'Checking value from tload after subcall ', 0x101); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TstorageReentrancyContextTest: 60806040525f805f6101000a81548160ff021916908315150217905550348015610027575f80fd5b506103de806100355f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80631ff644ef146100385780635f6813d114610042575b5f80fd5b61004061004c565b005b61004a61011c565b005b5f6040516024016040516020818303038152906040527f1ff644ef000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f54805f81146100ed5761010160ff5d60ff5c600455610117565b60015f5561010060ff5d60ff5c60035560025f525f808451602086015f305af160015560ff5c6002555b505050565b610143600354604051806060016040528060288152602001610301602891396101006101b9565b6101696001546040518060600160405280603081526020016103296030913960016101b9565b610190600454604051806060016040528060288152602001610381602891396101016101b9565b6101b7600254604051806060016040528060288152602001610359602891396101016101b9565b565b8083036101f1577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161022b565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516102229291906102d2565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561026757808201518184015260208101905061024c565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61028c82610230565b610296818561023a565b93506102a681856020860161024a565b6102af81610272565b840191505092915050565b5f819050919050565b6102cc816102ba565b82525050565b5f6040820190508181035f8301526102ea8185610282565b90506102f960208301846102c3565b939250505056fe436865636b696e672076616c75652066726f6d20746c6f6164206265666f72652073756263616c6c436865636b696e6720726573756c742063616c6c656520657865637574696f6e20697320776974682073756363657373436865636b696e672076616c75652066726f6d20746c6f61642061667465722073756263616c6c20436865636b696e672076616c75652066726f6d20746c6f616420696e736964652073756263616c6ca26469706673582212205eaa2b45243abfc23eb1044a5fe2ff7c133a9d27dc7ee1836eed96d02a8919ea64736f6c63430008180033 + +5f6813d1: checkValuesStoredInTstorage() +1ff644ef: manipulateInReentrantCall() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstorageReentrancyContextTest contract +transaction_build txTstorageReentrancyContextTestContract + sender acc1 + receiverAddress 00 + value 0 + data 60806040525f805f6101000a81548160ff021916908315150217905550348015610027575f80fd5b506103de806100355f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80631ff644ef146100385780635f6813d114610042575b5f80fd5b61004061004c565b005b61004a61011c565b005b5f6040516024016040516020818303038152906040527f1ff644ef000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f54805f81146100ed5761010160ff5d60ff5c600455610117565b60015f5561010060ff5d60ff5c60035560025f525f808451602086015f305af160015560ff5c6002555b505050565b610143600354604051806060016040528060288152602001610301602891396101006101b9565b6101696001546040518060600160405280603081526020016103296030913960016101b9565b610190600454604051806060016040528060288152602001610381602891396101016101b9565b6101b7600254604051806060016040528060288152602001610359602891396101016101b9565b565b8083036101f1577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161022b565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516102229291906102d2565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561026757808201518184015260208101905061024c565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61028c82610230565b610296818561023a565b93506102a681856020860161024a565b6102af81610272565b840191505092915050565b5f819050919050565b6102cc816102ba565b82525050565b5f6040820190508181035f8301526102ea8185610282565b90506102f960208301846102c3565b939250505056fe436865636b696e672076616c75652066726f6d20746c6f6164206265666f72652073756263616c6c436865636b696e6720726573756c742063616c6c656520657865637574696f6e20697320776974682073756363657373436865636b696e672076616c75652066726f6d20746c6f61642061667465722073756263616c6c20436865636b696e672076616c75652066726f6d20746c6f616420696e736964652073756263616c6ca26469706673582212205eaa2b45243abfc23eb1044a5fe2ff7c133a9d27dc7ee1836eed96d02a8919ea64736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txTstorageReentrancyContextTestContract transaction +block_build b01 + parent g00 + transactions txTstorageReentrancyContextTestContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txManipulateInReentrantCall transaction +transaction_build txManipulateInReentrantCall + sender acc1 + nonce 1 + contract txTstorageReentrancyContextTestContract + value 0 + data 1ff644ef + gas 300000 + build + +# Create block to hold txManipulateInReentrantCall transaction +block_build b02 + parent b01 + transactions txManipulateInReentrantCall + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 + +# Create transaction to execute txCheckValuesStoredInTstorage transaction +transaction_build txCheckValuesStoredInTstorage transaction + sender acc1 + nonce 2 + contract txTstorageReentrancyContextTestContract + value 0 + data 5f6813d1 + gas 300000 + build + +# Create block to hold txCheckValuesStoredInTstorage transaction +block_build b03 + parent b02 + transactions txCheckValuesStoredInTstorage + gasLimit 350000 + build + +# Connect block +block_connect b03 + +# Check b03 is best block +assert_best b03 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_tload_after_reentrant_tstore.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_tload_after_reentrant_tstore.txt new file mode 100644 index 00000000000..e807c54741f --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_tload_after_reentrant_tstore.txt @@ -0,0 +1,133 @@ +comment + +// CONTRACT CODE + +pragma solidity ^0.8.24; + +contract TstorageReentrancyContextTest { + bool reentrant = false; + uint256 success; + uint256 valueLoadedAfterSubcall; + uint256 valueLoadedBeforeSubcall; + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function tLoadAfterReentrantTstore() external { + bytes memory data = abi.encodeWithSignature("tLoadAfterReentrantTstore()"); + + assembly { + let reentrantValue := sload(reentrant.slot) + switch reentrantValue + case 0 { + sstore(reentrant.slot, true) + + tstore(0xFF, 0x100) + sstore(valueLoadedBeforeSubcall.slot, tload(0xFF)) + mstore(0, 2) + sstore(success.slot, call(gas(), address(), 0, add(data, 0x20), mload(data), 0, 0)) + sstore(valueLoadedAfterSubcall.slot, tload(0xFF)) + } + default { + tstore(0xFF, 0x101) + } + } + } + + function checkValuesStoredInTstorageCase() external { + checkReturnValueExpected(valueLoadedBeforeSubcall, 'Checking value from tload before subcall', 0x100); + checkReturnValueExpected(success, 'Checking result callee execution is with success', 1); + checkReturnValueExpected(valueLoadedAfterSubcall, 'Checking value from tload after subcall ', 0x101); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TstorageReentrancyContextTest: 60806040525f805f6101000a81548160ff021916908315150217905550348015610027575f80fd5b50610389806100355f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80635ecc5be5146100385780635f6813d114610042575b5f80fd5b61004061004c565b005b61004a610116565b005b5f6040516024016040516020818303038152906040527f5ecc5be5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f54805f81146100e75761010160ff5d610111565b60015f5561010060ff5d60ff5c60035560025f525f808451602086015f305af160015560ff5c6002555b505050565b61013d6003546040518060600160405280602881526020016102d46028913961010061018c565b6101636001546040518060600160405280603081526020016102fc60309139600161018c565b61018a60025460405180606001604052806028815260200161032c6028913961010161018c565b565b8083036101c4577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101fe565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516101f59291906102a5565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561023a57808201518184015260208101905061021f565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61025f82610203565b610269818561020d565b935061027981856020860161021d565b61028281610245565b840191505092915050565b5f819050919050565b61029f8161028d565b82525050565b5f6040820190508181035f8301526102bd8185610255565b90506102cc6020830184610296565b939250505056fe436865636b696e672076616c75652066726f6d20746c6f6164206265666f72652073756263616c6c436865636b696e6720726573756c742063616c6c656520657865637574696f6e20697320776974682073756363657373436865636b696e672076616c75652066726f6d20746c6f61642061667465722073756263616c6c20a264697066735822122051c2d1c8d7ba9ee8ee19a56961f0bb6c1a00450d360d92729994011b727dafac64736f6c63430008180033 + +5f6813d1: checkValuesStoredInTstorage() +5ecc5be5: tLoadAfterReentrantTstore() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstorageReentrancyContextTest contract +transaction_build txTstorageReentrancyContextTestContract + sender acc1 + receiverAddress 00 + value 0 + data 60806040525f805f6101000a81548160ff021916908315150217905550348015610027575f80fd5b50610389806100355f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80635ecc5be5146100385780635f6813d114610042575b5f80fd5b61004061004c565b005b61004a610116565b005b5f6040516024016040516020818303038152906040527f5ecc5be5000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f54805f81146100e75761010160ff5d610111565b60015f5561010060ff5d60ff5c60035560025f525f808451602086015f305af160015560ff5c6002555b505050565b61013d6003546040518060600160405280602881526020016102d46028913961010061018c565b6101636001546040518060600160405280603081526020016102fc60309139600161018c565b61018a60025460405180606001604052806028815260200161032c6028913961010161018c565b565b8083036101c4577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101fe565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516101f59291906102a5565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561023a57808201518184015260208101905061021f565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61025f82610203565b610269818561020d565b935061027981856020860161021d565b61028281610245565b840191505092915050565b5f819050919050565b61029f8161028d565b82525050565b5f6040820190508181035f8301526102bd8185610255565b90506102cc6020830184610296565b939250505056fe436865636b696e672076616c75652066726f6d20746c6f6164206265666f72652073756263616c6c436865636b696e6720726573756c742063616c6c656520657865637574696f6e20697320776974682073756363657373436865636b696e672076616c75652066726f6d20746c6f61642061667465722073756263616c6c20a264697066735822122051c2d1c8d7ba9ee8ee19a56961f0bb6c1a00450d360d92729994011b727dafac64736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txTstorageReentrancyContextTestContract transaction +block_build b01 + parent g00 + transactions txTstorageReentrancyContextTestContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txTloadAfterReentrantTstorel transaction +transaction_build txTloadAfterReentrantTstore + sender acc1 + nonce 1 + contract txTstorageReentrancyContextTestContract + value 0 + data 5ecc5be5 + gas 300000 + build + +# Create block to hold txTloadAfterReentrantTstore transaction +block_build b02 + parent b01 + transactions txTloadAfterReentrantTstore + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 + +# Create transaction to execute txCheckValuesStoredInTstorage transaction +transaction_build txCheckValuesStoredInTstorage transaction + sender acc1 + nonce 2 + contract txTstorageReentrancyContextTestContract + value 0 + data 5f6813d1 + gas 300000 + build + +# Create block to hold txCheckValuesStoredInTstorage transaction +block_build b03 + parent b02 + transactions txCheckValuesStoredInTstorage + gasLimit 350000 + build + +# Connect block +block_connect b03 + +# Check b03 is best block +assert_best b03 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_tstore_after_reentrant_call.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_tstore_after_reentrant_call.txt new file mode 100644 index 00000000000..eee111ba94c --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_tstore_after_reentrant_call.txt @@ -0,0 +1,105 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TstorageReentrancyContextTest { + bool reentrant = false; + uint256 success; + uint256 valueLoadedAfterSubcall; + uint256 valueLoadedInsideSubcall; + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function tstoreInReentrantCall() external { + bytes memory data = abi.encodeWithSignature("tstoreInReentrantCall()"); + + assembly { + let reentrantValue := sload(reentrant.slot) + switch reentrantValue + case 0 { + sstore(reentrant.slot, true) + + tstore(0, 0x100) + mstore(0, 2) + sstore(success.slot, call(gas(), address(), 0, add(data, 0x20), mload(data), 0, 0)) + sstore(valueLoadedAfterSubcall.slot, tload(0)) + } + default { + sstore(valueLoadedInsideSubcall.slot, tload(0)) + } + } + } + + function checkValuesStoredInTstorage() external { + checkReturnValueExpected(valueLoadedInsideSubcall, 'Checking value from tload inside subcall', 0x100); + checkReturnValueExpected(success, 'Checking result callee execution is with success', 1); + checkReturnValueExpected(valueLoadedAfterSubcall, 'Checking value from tload after subcall ', 0x100); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TstorageReentrancyContextTest: 60806040525f805f6101000a81548160ff021916908315150217905550348015610027575f80fd5b50610380806100355f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806321b76bb4146100385780635f6813d114610042575b5f80fd5b61004061004c565b005b61004a61010d565b005b5f6040516024016040516020818303038152906040527f21b76bb4000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f54805f81146100e6575f5c600355610108565b60015f556101005f5d60025f525f808451602086015f305af16001555f5c6002555b505050565b61013460035460405180606001604052806028815260200161032360289139610100610183565b61015a6001546040518060600160405280603081526020016102cb603091396001610183565b6101816002546040518060600160405280602881526020016102fb60289139610100610183565b565b8083036101bb577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101f5565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516101ec92919061029c565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610231578082015181840152602081019050610216565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610256826101fa565b6102608185610204565b9350610270818560208601610214565b6102798161023c565b840191505092915050565b5f819050919050565b61029681610284565b82525050565b5f6040820190508181035f8301526102b4818561024c565b90506102c3602083018461028d565b939250505056fe436865636b696e6720726573756c742063616c6c656520657865637574696f6e20697320776974682073756363657373436865636b696e672076616c75652066726f6d20746c6f61642061667465722073756263616c6c20436865636b696e672076616c75652066726f6d20746c6f616420696e736964652073756263616c6ca2646970667358221220aa4b50d0af36690596f713b131408b71aefedd3207a7ddee4c16a2924f23811464736f6c63430008180033 + +5f6813d1: checkValuesStoredInTstorage() +21b76bb4: tstoreInReentrantCall() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstorageReentrancyContextTest contract +transaction_build txTstorageReentrancyContextTestContract + sender acc1 + receiverAddress 00 + value 0 + data 60806040525f805f6101000a81548160ff021916908315150217905550348015610027575f80fd5b50610380806100355f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806321b76bb4146100385780635f6813d114610042575b5f80fd5b61004061004c565b005b61004a61010d565b005b5f6040516024016040516020818303038152906040527f21b76bb4000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f54805f81146100e6575f5c600355610108565b60015f556101005f5d60025f525f808451602086015f305af16001555f5c6002555b505050565b61013460035460405180606001604052806028815260200161032360289139610100610183565b61015a6001546040518060600160405280603081526020016102cb603091396001610183565b6101816002546040518060600160405280602881526020016102fb60289139610100610183565b565b8083036101bb577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101f5565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516101ec92919061029c565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610231578082015181840152602081019050610216565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610256826101fa565b6102608185610204565b9350610270818560208601610214565b6102798161023c565b840191505092915050565b5f819050919050565b61029681610284565b82525050565b5f6040820190508181035f8301526102b4818561024c565b90506102c3602083018461028d565b939250505056fe436865636b696e6720726573756c742063616c6c656520657865637574696f6e20697320776974682073756363657373436865636b696e672076616c75652066726f6d20746c6f61642061667465722073756263616c6c20436865636b696e672076616c75652066726f6d20746c6f616420696e736964652073756263616c6ca2646970667358221220aa4b50d0af36690596f713b131408b71aefedd3207a7ddee4c16a2924f23811464736f6c63430008180033 + gas 1000000 + build + +# Create transaction to execute txTstoreInReentrantCall transaction +transaction_build txTstoreInReentrantCall + sender acc1 + nonce 1 + contract txTstorageReentrancyContextTestContract + value 0 + data 21b76bb4 + gas 300000 + build + +# Create transaction to execute txCheckValuesStoredInTstorage transaction +transaction_build txCheckValuesStoredInTstorage transaction + sender acc1 + nonce 2 + contract txTstorageReentrancyContextTestContract + value 0 + data 5f6813d1 + gas 300000 + build + +# Create block to hold txCheckValuesStoredInTstorage transaction +block_build b01 + parent g00 + transactions txTstorageReentrancyContextTestContract txTstoreInReentrantCall txCheckValuesStoredInTstorage + gasLimit 3500000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_tstore_in_call_then_tload_return_in_static_call.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_tstore_in_call_then_tload_return_in_static_call.txt new file mode 100644 index 00000000000..68bbcf8c046 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/reentrancy_context_tstore_in_call_then_tload_return_in_static_call.txt @@ -0,0 +1,149 @@ +comment + +// CONTRACT CODE + +pragma solidity ^0.8.24; + +contract TstorageReentrancyContext { + uint256 reentrantCounter = 0; + uint256 valueLoadedFromFFBeforeDefaultCall; + uint256 valueLoadedFromFEAfterCall; + uint256 valueLoadedFromMloadAfterSecondReentrantCall; + uint256 resultFirstReentrantCall; + uint256 resultSecondReentrantStaticCall; + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function tstoreInCallThenTloadReturnInStaticCall() external { + bytes memory data = abi.encodeWithSignature("tstoreInCallThenTloadReturnInStaticCall()"); + + assembly { + let reentrantValue := sload(reentrantCounter.slot) + switch reentrantValue + case 1 { + // +1 to the counter so it goes to the other case from reentrant call + reentrantValue := add(reentrantValue, 1) + sstore(reentrantCounter.slot, reentrantValue) + tstore(0xFE, 0x101) + sstore(resultSecondReentrantStaticCall.slot, staticcall(gas(), address(), add(data, 0x20), mload(data), 0, 32)) + sstore(valueLoadedFromMloadAfterSecondReentrantCall.slot, mload(0)) + } + case 2 { + let value := tload(0xFE) + mstore(0, value) + return(0, 32) + } + default { + // +1 to the counter so it goes to the other case from reentrant call + reentrantValue := add(reentrantValue, 1) + sstore(reentrantCounter.slot, reentrantValue) + + // Setup the conditions to be tested + tstore(0xFF, 0x100) + sstore(valueLoadedFromFFBeforeDefaultCall.slot, tload(0xFF)) + sstore(resultFirstReentrantCall.slot, call(gas(), address(), 0, add(data, 0x20), mload(data), 0, 0)) // saves result from the call so we can check later + sstore(valueLoadedFromFEAfterCall.slot, tload(0xFE)) + } + } + } + + function checkValuesStoredInTstorage() external { + checkReturnValueExpected(resultFirstReentrantCall, 'Checking result callee execution resultFirstReentrantCall is success', 1); + checkReturnValueExpected(resultSecondReentrantStaticCall, 'Checking result callee execution resultSecondReentrantCall is success', 1); + checkReturnValueExpected(valueLoadedFromFFBeforeDefaultCall, 'Checking value from tload FF before default call', 0x100); + checkReturnValueExpected(valueLoadedFromMloadAfterSecondReentrantCall, 'Checking value from FE after second reentrant call', 0x101); + checkReturnValueExpected(valueLoadedFromFEAfterCall, 'Checking value from tload FE after defaul call', 0x101); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +// CONTRACT BYTECODE + +TstorageReentrancyContext: 60806040525f8055348015610012575f80fd5b506104a5806100205f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c8063586c69f3146100385780635f6813d114610042575b5f80fd5b61004061004c565b005b61004a61014c565b005b5f6040516024016040516020818303038152906040527f586c69f3000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f548060018114610114576002811461013c57600182019150815f5561010060ff5d60ff5c6001555f808451602086015f305af160045560fe5c600255610147565b600182019150815f5561010160fe5d60205f845160208601305afa6005555f51600355610147565b60fe5c805f5260205ff35b505050565b6101726004546040518060800160405280604481526020016103ce60449139600161020f565b61019860055460405180608001604052806045815260200161035760459139600161020f565b6101bf6001546040518060600160405280603081526020016104126030913961010061020f565b6101e660035460405180606001604052806032815260200161039c6032913961010161020f565b61020d6002546040518060600160405280602e8152602001610442602e913961010161020f565b565b808303610247577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610281565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610278929190610328565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156102bd5780820151818401526020810190506102a2565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6102e282610286565b6102ec8185610290565b93506102fc8185602086016102a0565b610305816102c8565b840191505092915050565b5f819050919050565b61032281610310565b82525050565b5f6040820190508181035f83015261034081856102d8565b905061034f6020830184610319565b939250505056fe436865636b696e6720726573756c742063616c6c656520657865637574696f6e20726573756c745365636f6e645265656e7472616e7443616c6c2069732073756363657373436865636b696e672076616c75652066726f6d204645206166746572207365636f6e64207265656e7472616e742063616c6c436865636b696e6720726573756c742063616c6c656520657865637574696f6e20726573756c7446697273745265656e7472616e7443616c6c2069732073756363657373436865636b696e672076616c75652066726f6d20746c6f6164204646206265666f72652064656661756c742063616c6c436865636b696e672076616c75652066726f6d20746c6f61642046452061667465722064656661756c2063616c6ca2646970667358221220fb81ff9160d8fbb79af6b7a0900873b90768b55016a5ae78f0763585a925688064736f6c63430008180033 + +5f6813d1: checkValuesStoredInTstorage() +586c69f3: tstoreInCallThenTloadReturnInStaticCall() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstorageReentrancyContextTest contract +transaction_build txTstorageReentrancyContextTestContract + sender acc1 + receiverAddress 00 + value 0 + data 60806040525f8055348015610012575f80fd5b506104a5806100205f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c8063586c69f3146100385780635f6813d114610042575b5f80fd5b61004061004c565b005b61004a61014c565b005b5f6040516024016040516020818303038152906040527f586c69f3000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090505f548060018114610114576002811461013c57600182019150815f5561010060ff5d60ff5c6001555f808451602086015f305af160045560fe5c600255610147565b600182019150815f5561010160fe5d60205f845160208601305afa6005555f51600355610147565b60fe5c805f5260205ff35b505050565b6101726004546040518060800160405280604481526020016103ce60449139600161020f565b61019860055460405180608001604052806045815260200161035760459139600161020f565b6101bf6001546040518060600160405280603081526020016104126030913961010061020f565b6101e660035460405180606001604052806032815260200161039c6032913961010161020f565b61020d6002546040518060600160405280602e8152602001610442602e913961010161020f565b565b808303610247577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610281565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610278929190610328565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156102bd5780820151818401526020810190506102a2565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6102e282610286565b6102ec8185610290565b93506102fc8185602086016102a0565b610305816102c8565b840191505092915050565b5f819050919050565b61032281610310565b82525050565b5f6040820190508181035f83015261034081856102d8565b905061034f6020830184610319565b939250505056fe436865636b696e6720726573756c742063616c6c656520657865637574696f6e20726573756c745365636f6e645265656e7472616e7443616c6c2069732073756363657373436865636b696e672076616c75652066726f6d204645206166746572207365636f6e64207265656e7472616e742063616c6c436865636b696e6720726573756c742063616c6c656520657865637574696f6e20726573756c7446697273745265656e7472616e7443616c6c2069732073756363657373436865636b696e672076616c75652066726f6d20746c6f6164204646206265666f72652064656661756c742063616c6c436865636b696e672076616c75652066726f6d20746c6f61642046452061667465722064656661756c2063616c6ca2646970667358221220fb81ff9160d8fbb79af6b7a0900873b90768b55016a5ae78f0763585a925688064736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txTstorageReentrancyContextTestContract transaction +block_build b01 + parent g00 + transactions txTstorageReentrancyContextTestContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txTstorageInReentrantCallTest transaction +transaction_build txTstorageInReentrantCallTest + sender acc1 + nonce 1 + contract txTstorageReentrancyContextTestContract + value 0 + data 586c69f3 + gas 300000 + build + +# Create block to hold txTstorageInReentrantCallTest transaction +block_build b02 + parent b01 + transactions txTstorageInReentrantCallTest + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 + +# Create transaction to execute txCheckValuesStoredInTstorage transaction +transaction_build txCheckValuesStoredInTstorage transaction + sender acc1 + nonce 2 + contract txTstorageReentrancyContextTestContract + value 0 + data 5f6813d1 + gas 300000 + build + +# Create block to hold txCheckValuesStoredInTstorage transaction +block_build b03 + parent b02 + transactions txCheckValuesStoredInTstorage + gasLimit 350000 + build + +# Connect block +block_connect b03 + +# Check b03 is best block +assert_best b03 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_inner_selfdestruct_new_contract.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_inner_selfdestruct_new_contract.txt new file mode 100644 index 00000000000..4aeaf2dbd12 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_inner_selfdestruct_new_contract.txt @@ -0,0 +1,136 @@ +comment + +// CONTRACT CODE + +pragma solidity ^0.8.24; + +contract TloadAfterInnerSelfdestructingNewContract { + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function performTest() external { + Callee callee = new Callee(); + address calleeAddress = address(callee); + uint256 resultCallOption1; + uint256 valueLoadedFromMemory; + bytes4 executeSignature = bytes4(keccak256("execute(uint256)")); + + assembly { + // Call Option 1: Executes tstore, inner call to selfdestruct and then tload and return data + let availablePointerCallOption1 := mload(0x40) + mstore(availablePointerCallOption1, executeSignature) + mstore(add(availablePointerCallOption1, 4), 1) + resultCallOption1 := call(gas(), calleeAddress, 0, availablePointerCallOption1, 0x24, availablePointerCallOption1, 0x20) + + // Copy returndata into memory to retrieve the returned value + returndatacopy(availablePointerCallOption1, 0, returndatasize()) + valueLoadedFromMemory := mload(availablePointerCallOption1) + } + + checkReturnValueExpected(resultCallOption1, 'Checking result call option 1', 0x01); + checkReturnValueExpected(valueLoadedFromMemory, 'Checking value from mload 0', 0x100); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + event OK(); + event ERROR(string, uint256); + + function execute(uint256 callOption) external returns (uint256) { + address calleeAddress = address(this); + bytes4 executeSignature = bytes4(keccak256("execute(uint256)")); + uint256 resultCallOption2; + assembly { + switch callOption + case 1 { + tstore(0xFF, 0x100) + // Call Option 2: Executes tload and returns data + let availablePointerCallOption2 := mload(0x40) + mstore(availablePointerCallOption2, executeSignature) + mstore(add(availablePointerCallOption2, 4), 2) + resultCallOption2 := call(gas(), calleeAddress, 0, availablePointerCallOption2, 0x24, availablePointerCallOption2, 0x20) + + // Load value from transient storage + let value := tload(0xFF) + mstore(0x00, value) // Store it in memory to return + return(0x00, 0x20) // Return 32 bytes from memory + } + case 2 { + selfdestruct(0) + } + } + } +} + +// DESCRIPTION + +// CONTRACT BYTECODE + +TloadAfterInnerSelfdestructingNewContract: 608060405234801561000f575f80fd5b506104708061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f604051610044906101ad565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f8190505f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f895af193503d5f823e80519250506100ed836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20310000008152506001610136565b61012f826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f616420300000000000815250610100610136565b5050505050565b80830361016e577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101a8565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161019f92919061025c565b60405180910390a15b505050565b6101b08061028b83390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101f15780820151818401526020810190506101d6565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610216826101ba565b61022081856101c4565b93506102308185602086016101d4565b610239816101fc565b840191505092915050565b5f819050919050565b61025681610244565b82525050565b5f6040820190508181035f830152610274818561020c565b9050610283602083018461024d565b939250505056fe608060405234801561000f575f80fd5b506101938061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b6100476004803603810190610042919061010a565b61005d565b6040516100549190610144565b60405180910390f35b5f803090505f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b90505f846001811461009d57600281146100c7576100ca565b61010060ff5d604051838152600260048201526020816024835f895af1925060ff5c805f5260205ff35b5fff5b50505050919050565b5f80fd5b5f819050919050565b6100e9816100d7565b81146100f3575f80fd5b50565b5f81359050610104816100e0565b92915050565b5f6020828403121561011f5761011e6100d3565b5b5f61012c848285016100f6565b91505092915050565b61013e816100d7565b82525050565b5f6020820190506101575f830184610135565b9291505056fea2646970667358221220df3fda34f805973d73508c3bff5aa075ac36fd7769240906d19a4ade4713155464736f6c63430008180033a26469706673582212202ee0175c4410ed0d1259c8ad0377835933ddf29c77105e09bac218f55b6c5f3464736f6c63430008180033 + +function hashes:s + +- 0d0b85f1: performTest() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TloadAfterSelfdestructPreExistingContract contract +transaction_build txDeployTestContract + sender acc1 + receiverAddress 00 + value 0 + data 608060405234801561000f575f80fd5b506104708061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f604051610044906101ad565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f8190505f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f895af193503d5f823e80519250506100ed836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20310000008152506001610136565b61012f826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f616420300000000000815250610100610136565b5050505050565b80830361016e577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101a8565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161019f92919061025c565b60405180910390a15b505050565b6101b08061028b83390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101f15780820151818401526020810190506101d6565b5f8484015250505050565b5f601f19601f8301169050919050565b5f610216826101ba565b61022081856101c4565b93506102308185602086016101d4565b610239816101fc565b840191505092915050565b5f819050919050565b61025681610244565b82525050565b5f6040820190508181035f830152610274818561020c565b9050610283602083018461024d565b939250505056fe608060405234801561000f575f80fd5b506101938061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b6100476004803603810190610042919061010a565b61005d565b6040516100549190610144565b60405180910390f35b5f803090505f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b90505f846001811461009d57600281146100c7576100ca565b61010060ff5d604051838152600260048201526020816024835f895af1925060ff5c805f5260205ff35b5fff5b50505050919050565b5f80fd5b5f819050919050565b6100e9816100d7565b81146100f3575f80fd5b50565b5f81359050610104816100e0565b92915050565b5f6020828403121561011f5761011e6100d3565b5b5f61012c848285016100f6565b91505092915050565b61013e816100d7565b82525050565b5f6020820190506101575f830184610135565b9291505056fea2646970667358221220df3fda34f805973d73508c3bff5aa075ac36fd7769240906d19a4ade4713155464736f6c63430008180033a26469706673582212202ee0175c4410ed0d1259c8ad0377835933ddf29c77105e09bac218f55b6c5f3464736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txDeployTestContract transaction +block_build b01 + parent g00 + transactions txDeployTestContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute performTest function from contract +transaction_build txPerformTest + sender acc1 + nonce 1 + contract txDeployTestContract + value 0 + data 0d0b85f1 + gas 300000 + build + +# Create block to hold txPerformTest transaction +block_build b02 + parent b01 + transactions txPerformTest + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_inner_selfdestruct_pre_existing_contract.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_inner_selfdestruct_pre_existing_contract.txt new file mode 100644 index 00000000000..c9aa4f4565f --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_inner_selfdestruct_pre_existing_contract.txt @@ -0,0 +1,136 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TloadAfterInnerSelfdestructingPreExistingContract { + Callee callee; + + constructor() { + callee = new Callee(); + } + + event OK(); + event ERROR(string, uint256); + + function performTest() external { + address calleeAddress = address(callee); + uint256 resultCallOption1; + uint256 valueLoadedFromMemory; + bytes4 executeSignature = bytes4(keccak256("execute(uint256)")); + + assembly { + // Call Option 1: Executes tstore, inner call to selfdestruct and then tload and return data + let availablePointerCallOption1 := mload(0x40) + mstore(availablePointerCallOption1, executeSignature) + mstore(add(availablePointerCallOption1, 4), 1) + resultCallOption1 := call(gas(), calleeAddress, 0, availablePointerCallOption1, 0x24, availablePointerCallOption1, 0x20) + + // Copy returndata into memory to retrieve the returned value + returndatacopy(availablePointerCallOption1, 0, returndatasize()) + valueLoadedFromMemory := mload(availablePointerCallOption1) + } + + checkReturnValueExpected(resultCallOption1, 'Checking result call option 1', 0x01); + checkReturnValueExpected(valueLoadedFromMemory, 'Checking value from mload 0', 0x100); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + event OK(); + event ERROR(string, uint256); + + function execute(uint256 callOption) external returns (uint256) { + address calleeAddress = address(this); + bytes4 executeSignature = bytes4(keccak256("execute(uint256)")); + uint256 resultCallOption2; + assembly { + switch callOption + case 1 { + tstore(0xFF, 0x100) + // Call Option 2: Executes tload and returns data + let availablePointerCallOption2 := mload(0x40) + mstore(availablePointerCallOption2, executeSignature) + mstore(add(availablePointerCallOption2, 4), 2) + resultCallOption2 := call(gas(), calleeAddress, 0, availablePointerCallOption2, 0x24, availablePointerCallOption2, 0x20) + + // Load value from transient storage + let value := tload(0xFF) + mstore(0x00, value) // Store it in memory to return + return(0x00, 0x20) // Return 32 bytes from memory + } + case 2 { + selfdestruct(0) + } + } + } +} + +// DESCRIPTION + +// CONTRACT BYTECODE + +TloadAfterInnerSelfdestructingPreExistingContract: 608060405234801561000f575f80fd5b5060405161001c90610079565b604051809103905ff080158015610035573d5f803e3d5ffd5b505f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610086565b6101b08061033c83390190565b6102a9806100935f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f895af193503d5f823e80519250506100e4836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e2031000000815250600161012c565b610126826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f61642030000000000081525061010061012c565b50505050565b808303610164577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161019e565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610195929190610245565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101da5780820151818401526020810190506101bf565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6101ff826101a3565b61020981856101ad565b93506102198185602086016101bd565b610222816101e5565b840191505092915050565b5f819050919050565b61023f8161022d565b82525050565b5f6040820190508181035f83015261025d81856101f5565b905061026c6020830184610236565b939250505056fea2646970667358221220314f4ea23497493d6086e14a2ebfdd4290728740c02f4713001e260d7d662c4164736f6c63430008180033608060405234801561000f575f80fd5b506101938061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b6100476004803603810190610042919061010a565b61005d565b6040516100549190610144565b60405180910390f35b5f803090505f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b90505f846001811461009d57600281146100c7576100ca565b61010060ff5d604051838152600260048201526020816024835f895af1925060ff5c805f5260205ff35b5fff5b50505050919050565b5f80fd5b5f819050919050565b6100e9816100d7565b81146100f3575f80fd5b50565b5f81359050610104816100e0565b92915050565b5f6020828403121561011f5761011e6100d3565b5b5f61012c848285016100f6565b91505092915050565b61013e816100d7565b82525050565b5f6020820190506101575f830184610135565b9291505056fea264697066735822122000dadba91902cd6d3eaf38fdb47cdccbbf9036448d79da3ff9b15dc0012e4a0864736f6c63430008180033 + +function hashes:s + +- 0d0b85f1: performTest() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TloadAfterSelfdestructPreExistingContract contract +transaction_build txDeployTestContract + sender acc1 + receiverAddress 00 + value 0 + data 608060405234801561000f575f80fd5b5060405161001c90610079565b604051809103905ff080158015610035573d5f803e3d5ffd5b505f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610086565b6101b08061033c83390190565b6102a9806100935f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f895af193503d5f823e80519250506100e4836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e2031000000815250600161012c565b610126826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f61642030000000000081525061010061012c565b50505050565b808303610164577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161019e565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610195929190610245565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156101da5780820151818401526020810190506101bf565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6101ff826101a3565b61020981856101ad565b93506102198185602086016101bd565b610222816101e5565b840191505092915050565b5f819050919050565b61023f8161022d565b82525050565b5f6040820190508181035f83015261025d81856101f5565b905061026c6020830184610236565b939250505056fea2646970667358221220314f4ea23497493d6086e14a2ebfdd4290728740c02f4713001e260d7d662c4164736f6c63430008180033608060405234801561000f575f80fd5b506101938061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b6100476004803603810190610042919061010a565b61005d565b6040516100549190610144565b60405180910390f35b5f803090505f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b90505f846001811461009d57600281146100c7576100ca565b61010060ff5d604051838152600260048201526020816024835f895af1925060ff5c805f5260205ff35b5fff5b50505050919050565b5f80fd5b5f819050919050565b6100e9816100d7565b81146100f3575f80fd5b50565b5f81359050610104816100e0565b92915050565b5f6020828403121561011f5761011e6100d3565b5b5f61012c848285016100f6565b91505092915050565b61013e816100d7565b82525050565b5f6020820190506101575f830184610135565b9291505056fea264697066735822122000dadba91902cd6d3eaf38fdb47cdccbbf9036448d79da3ff9b15dc0012e4a0864736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txDeployTestContract transaction +block_build b01 + parent g00 + transactions txDeployTestContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute performTest function from contract +transaction_build txPerformTest + sender acc1 + nonce 1 + contract txDeployTestContract + value 0 + data 0d0b85f1 + gas 300000 + build + +# Create block to hold txPerformTest transaction +block_build b02 + parent b01 + transactions txPerformTest + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_selfdestruct_new_contract.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_selfdestruct_new_contract.txt new file mode 100644 index 00000000000..ef46b4f70d3 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_selfdestruct_new_contract.txt @@ -0,0 +1,132 @@ +comment + +// CONTRACT CODE + +pragma solidity ^0.8.24; + +contract TloadAfterSelfdestructNewContract { + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function performTest() external { + Callee callee = new Callee(); + address calleeAddress = address(callee); + uint256 resultCallOption1; + uint256 resultCallOption2; + uint256 valueLoadedFromMemory; + bytes4 executeSignature = bytes4(keccak256("execute(uint256)")); + + assembly { + // Call Option 1: Executes tstore and selfdestruct + let availablePointerCallOption1 := mload(0x40) + mstore(availablePointerCallOption1, executeSignature) + mstore(add(availablePointerCallOption1, 4), 1) + resultCallOption1 := call(gas(), calleeAddress, 0, availablePointerCallOption1, 0x24, availablePointerCallOption1, 0x20) + // Note: Callee will self-destruct, no return data expected for callOption == 1. + + // Call Option 2: Executes tload and returns data + let availablePointerCallOption2 := mload(0x40) + mstore(availablePointerCallOption2, executeSignature) + mstore(add(availablePointerCallOption2, 4), 2) + resultCallOption2 := call(gas(), calleeAddress, 0, availablePointerCallOption2, 0x24, availablePointerCallOption2, 0x2) + + // Copy returndata into memory to retrieve the returned value + returndatacopy(availablePointerCallOption2, 0, returndatasize()) + valueLoadedFromMemory := mload(availablePointerCallOption2) + } + + checkReturnValueExpected(resultCallOption1, 'Checking result call option 1', 0x01); + checkReturnValueExpected(resultCallOption2, 'Checking result call option 2', 0x01); + checkReturnValueExpected(valueLoadedFromMemory, 'Checking value from mload 0', 0x100); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + function execute(uint256 callOption) external returns (uint256) { + assembly { + switch callOption + case 1 { + tstore(0xFF, 0x100) + selfdestruct(0) + } + case 2 { + // Load value from transient storage + let value := tload(0xFF) + mstore(0x00, value) // Store it in memory to return + return(0x00, 0x20) // Return 32 bytes from memory + } + } + } +} + +// DESCRIPTION + +// CONTRACT BYTECODE + +TloadAfterSelfdestructNewContract: 608060405234801561000f575f80fd5b506104888061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f6040516100449061020a565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f8190505f805f807ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f8a5af19450604051828152600260048201526002816024835f8b5af194503d5f823e805193505050610108846040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20310000008152506001610193565b610149836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20320000008152506001610193565b61018b826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f616420300000000000815250610100610193565b505050505050565b8083036101cb577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610205565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516101fc9291906102b9565b60405180910390a15b505050565b61016b806102e883390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561024e578082015181840152602081019050610233565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61027382610217565b61027d8185610221565b935061028d818560208601610231565b61029681610259565b840191505092915050565b5f819050919050565b6102b3816102a1565b82525050565b5f6040820190508181035f8301526102d18185610269565b90506102e060208301846102aa565b939250505056fe608060405234801561000f575f80fd5b5061014e8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b610047600480360381019061004291906100c5565b61005d565b60405161005491906100ff565b60405180910390f35b5f8160018114610074576002811461007d57610088565b61010060ff5d5fff5b60ff5c805f5260205ff35b50919050565b5f80fd5b5f819050919050565b6100a481610092565b81146100ae575f80fd5b50565b5f813590506100bf8161009b565b92915050565b5f602082840312156100da576100d961008e565b5b5f6100e7848285016100b1565b91505092915050565b6100f981610092565b82525050565b5f6020820190506101125f8301846100f0565b9291505056fea264697066735822122055ccf41b608b610b0f0b3c6343fb66efe3d487da32a8a6981a907e22d0d4722e64736f6c63430008180033a264697066735822122076e62ebfbdf54923ba4920877ca4a8354142b8a1b5a18492fd7b0f1da3956cb964736f6c63430008180033 + +function hashes:s + +- 0d0b85f1: performTest() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TloadAfterSelfdestructPreExistingContract contract +transaction_build txDeployTestContract + sender acc1 + receiverAddress 00 + value 0 + data 608060405234801561000f575f80fd5b506104888061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f6040516100449061020a565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f8190505f805f807ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f8a5af19450604051828152600260048201526002816024835f8b5af194503d5f823e805193505050610108846040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20310000008152506001610193565b610149836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20320000008152506001610193565b61018b826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f616420300000000000815250610100610193565b505050505050565b8083036101cb577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610205565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516101fc9291906102b9565b60405180910390a15b505050565b61016b806102e883390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561024e578082015181840152602081019050610233565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61027382610217565b61027d8185610221565b935061028d818560208601610231565b61029681610259565b840191505092915050565b5f819050919050565b6102b3816102a1565b82525050565b5f6040820190508181035f8301526102d18185610269565b90506102e060208301846102aa565b939250505056fe608060405234801561000f575f80fd5b5061014e8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b610047600480360381019061004291906100c5565b61005d565b60405161005491906100ff565b60405180910390f35b5f8160018114610074576002811461007d57610088565b61010060ff5d5fff5b60ff5c805f5260205ff35b50919050565b5f80fd5b5f819050919050565b6100a481610092565b81146100ae575f80fd5b50565b5f813590506100bf8161009b565b92915050565b5f602082840312156100da576100d961008e565b5b5f6100e7848285016100b1565b91505092915050565b6100f981610092565b82525050565b5f6020820190506101125f8301846100f0565b9291505056fea264697066735822122055ccf41b608b610b0f0b3c6343fb66efe3d487da32a8a6981a907e22d0d4722e64736f6c63430008180033a264697066735822122076e62ebfbdf54923ba4920877ca4a8354142b8a1b5a18492fd7b0f1da3956cb964736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txDeployTestContract transaction +block_build b01 + parent g00 + transactions txDeployTestContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute performTest function from contract +transaction_build txPerformTest + sender acc1 + nonce 1 + contract txDeployTestContract + value 0 + data 0d0b85f1 + gas 300000 + build + +# Create block to hold txPerformTest transaction +block_build b02 + parent b01 + transactions txPerformTest + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_selfdestruct_pre_existing_contract.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_selfdestruct_pre_existing_contract.txt new file mode 100644 index 00000000000..2ae3bbe240f --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_after_selfdestruct_pre_existing_contract.txt @@ -0,0 +1,130 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TloadAfterSelfdestructPreExistingContract { + Callee callee; + + constructor() { + callee = new Callee(); + } + + event OK(); + event ERROR(string, uint256); + + function performTest() external { + address calleeAddress = address(callee); + uint256 resultCallOption1; + uint256 resultCallOption2; + uint256 valueLoadedFromMemory; + bytes4 executeSignature = bytes4(keccak256("execute(uint256)")); + + assembly { + let availablePointerCallOption1 := mload(0x40) + mstore(availablePointerCallOption1, executeSignature) + mstore(add(availablePointerCallOption1, 4), 1) + resultCallOption1 := call(gas(), calleeAddress, 0, availablePointerCallOption1, 0x24, availablePointerCallOption1, 0x20) + + let availablePointerCallOption2 := mload(0x40) + mstore(availablePointerCallOption2, executeSignature) + mstore(add(availablePointerCallOption2, 4), 2) + resultCallOption2 := call(gas(), calleeAddress, 0, availablePointerCallOption2, 0x24, availablePointerCallOption2, 0x2) + + // Copy returndata into memory to retrieve the returned value + returndatacopy(availablePointerCallOption2, 0, returndatasize()) + valueLoadedFromMemory := mload(availablePointerCallOption2) + } + + checkReturnValueExpected(resultCallOption1, 'Checking result call option 1', 0x01); + checkReturnValueExpected(resultCallOption2, 'Checking result call option 2', 0x01); + checkReturnValueExpected(valueLoadedFromMemory, 'Checking value from mload 0', 0x100); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + function execute(uint256 callOption) external returns (uint256) { + assembly { + switch callOption + case 1 { + tstore(0xFF, 0x100) + selfdestruct(0) + } + case 2 { + // Load value from transient storage + let value := tload(0xFF) + mstore(0x00, value) // Store it in memory to return + return(0x00, 0x20) // Return 32 bytes from memory + } + } + } +} + +// DESCRIPTION + +// CONTRACT BYTECODE + +TloadAfterSelfdestructPreExistingContract: 608060405234801561000f575f80fd5b5060405161001c90610079565b604051809103905ff080158015610035573d5f803e3d5ffd5b505f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610086565b61016b8061039983390190565b610306806100935f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f807ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f8a5af19450604051828152600260048201526002816024835f8b5af194503d5f823e8051935050506100ff846040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20310000008152506001610189565b610140836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20320000008152506001610189565b610182826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f616420300000000000815250610100610189565b5050505050565b8083036101c1577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101fb565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516101f29291906102a2565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561023757808201518184015260208101905061021c565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61025c82610200565b610266818561020a565b935061027681856020860161021a565b61027f81610242565b840191505092915050565b5f819050919050565b61029c8161028a565b82525050565b5f6040820190508181035f8301526102ba8185610252565b90506102c96020830184610293565b939250505056fea26469706673582212205534fa1e929c43e2b37b29d413d4548878f2de78cb0752060df934815275576864736f6c63430008180033608060405234801561000f575f80fd5b5061014e8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b610047600480360381019061004291906100c5565b61005d565b60405161005491906100ff565b60405180910390f35b5f8160018114610074576002811461007d57610088565b61010060ff5d5fff5b60ff5c805f5260205ff35b50919050565b5f80fd5b5f819050919050565b6100a481610092565b81146100ae575f80fd5b50565b5f813590506100bf8161009b565b92915050565b5f602082840312156100da576100d961008e565b5b5f6100e7848285016100b1565b91505092915050565b6100f981610092565b82525050565b5f6020820190506101125f8301846100f0565b9291505056fea26469706673582212209845c65124ff773997c6f9fecd143ae783a790c95fab788e181664dce3129d7d64736f6c63430008180033 + +function hashes:s + +- 0d0b85f1: performTest() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TloadAfterSelfdestructPreExistingContract contract +transaction_build txDeployTestContract + sender acc1 + receiverAddress 00 + value 0 + data 608060405234801561000f575f80fd5b5060405161001c90610079565b604051809103905ff080158015610035573d5f803e3d5ffd5b505f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610086565b61016b8061039983390190565b610306806100935f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f807ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f8a5af19450604051828152600260048201526002816024835f8b5af194503d5f823e8051935050506100ff846040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20310000008152506001610189565b610140836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e20320000008152506001610189565b610182826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f616420300000000000815250610100610189565b5050505050565b8083036101c1577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101fb565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516101f29291906102a2565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b8381101561023757808201518184015260208101905061021c565b5f8484015250505050565b5f601f19601f8301169050919050565b5f61025c82610200565b610266818561020a565b935061027681856020860161021a565b61027f81610242565b840191505092915050565b5f819050919050565b61029c8161028a565b82525050565b5f6040820190508181035f8301526102ba8185610252565b90506102c96020830184610293565b939250505056fea26469706673582212205534fa1e929c43e2b37b29d413d4548878f2de78cb0752060df934815275576864736f6c63430008180033608060405234801561000f575f80fd5b5061014e8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b610047600480360381019061004291906100c5565b61005d565b60405161005491906100ff565b60405180910390f35b5f8160018114610074576002811461007d57610088565b61010060ff5d5fff5b60ff5c805f5260205ff35b50919050565b5f80fd5b5f819050919050565b6100a481610092565b81146100ae575f80fd5b50565b5f813590506100bf8161009b565b92915050565b5f602082840312156100da576100d961008e565b5b5f6100e7848285016100b1565b91505092915050565b6100f981610092565b82525050565b5f6020820190506101125f8301846100f0565b9291505056fea26469706673582212209845c65124ff773997c6f9fecd143ae783a790c95fab788e181664dce3129d7d64736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txDeployTestContract transaction +block_build b01 + parent g00 + transactions txDeployTestContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute performTest function from contract +transaction_build txPerformTest + sender acc1 + nonce 1 + contract txDeployTestContract + value 0 + data 0d0b85f1 + gas 300000 + build + +# Create block to hold txPerformTest transaction +block_build b02 + parent b01 + transactions txPerformTest + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_tstore_basic_tests.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_tstore_basic_tests.txt new file mode 100644 index 00000000000..0607af0de7a --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_tstore_basic_tests.txt @@ -0,0 +1,246 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TestTransientStorage { + constructor() {} + + event OK(); + event ERROR(bytes32); + + function checkTransientStorage(bytes32 key, bytes32 value) external { + bytes32 valueLoaded; + assembly { + tstore(key, value) + valueLoaded := tload(key) + } + if (valueLoaded == value) { + emit OK(); + } else { + emit ERROR(valueLoaded); + } + } + + function checkDataEqualsTheValuePassed(bytes32 key, bytes32 valueExpected) external { + bytes32 valueLoaded; + assembly { + valueLoaded := tload(key) + } + if (valueLoaded == valueExpected) { + emit OK(); + } else { + emit ERROR(valueLoaded); + } + } + + function checkIfNestedTransactionSameContractShareMemory(bytes32 key, bytes32 value) external { + assembly { + tstore(key, value) + } + this.checkDataEqualsTheValuePassed(key, value); + } + + function checkIfNestedTransactionFromOtherContractShareMemory(bytes32 key, bytes32 value) external { + assembly { + tstore(key, value) + } + new TestTransientStorageOtherContract().checkDataEqualsTheValuePassed(key, value); + } +} + +contract TestTransientStorageOtherContract{ + constructor() {} + + event OK(); + event ERROR(bytes32); + + function checkDataEqualsTheValuePassed(bytes32 key, bytes32 valueExpected) external { + bytes32 valueLoaded; + assembly { + valueLoaded := tload(key) + } + if (valueLoaded == valueExpected) { + emit OK(); + } else { + emit ERROR(valueLoaded); + } + } +} + +// DESCRIPTION + +TestTransientStorage has the following functions: + +* checkTransientStorage simply checks if the TSTORE and TLOAD functions are working properly. It stores a value in the transient storage and then loads it. If the loaded value is the same as the stored value, it emits an OK event. Otherwise, it emits an ERROR event. + +* checkDataEqualsTheValuePassed simply checks if the transaction TLOAD doesn't load a value that was not stored in the transient storage. It loads a value from the transient storage, if we haven't loaded with a nested transaction it will return 0 otherwise it will return the value stored. +If the value loaded is the same as the value passed as a parameter, it emits an OK event. Otherwise, it emits an ERROR event. + +* checkIfNestedTransactionSameContractShareMemory stores a value in the transient storage and then calls a function from the same contract that loads the value from the transient storage. This is to check if the transient storage is shared between nested transactions. + +* checkIfNestedTransactionFromOtherContractShareMemory stores a value in the transient storage and then calls a function from another contract that loads the value from the transient storage. This is to check if the transient storage is not shared between transactions. + +TestTransientStorageOtherContract has the following functions: + +* checkDataEqualsTheValuePassed simply checks if the transaction TLOAD doesn't load a value that was not stored in the transient storage. It loads a value from the transient storage, if we haven't loaded with a nested transaction it will return 0 otherwise it will return the value stored. +If the value loaded is the same as the value passed as a parameter, it emits an OK event. Otherwise, it emits an ERROR event. + +// CONTRACT BYTECODE + +TestTransientStorage: 6080604052348015600e575f80fd5b506105718061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80635dbdd0ce1461004e5780637b70ef4e1461006a5780637dccab6614610086578063f5cc67a1146100a2575b5f80fd5b610068600480360381019061006391906102fc565b6100be565b005b610084600480360381019061007f91906102fc565b61012d565b005b6100a0600480360381019061009b91906102fc565b6101c1565b005b6100bc60048036038101906100b791906102fc565b61023b565b005b80825d3073ffffffffffffffffffffffffffffffffffffffff16637dccab6683836040518363ffffffff1660e01b81526004016100fc929190610349565b5f604051808303815f87803b158015610113575f80fd5b505af1158015610125573d5f803e3d5ffd5b505050505050565b80825d60405161013c906102b8565b604051809103905ff080158015610155573d5f803e3d5ffd5b5073ffffffffffffffffffffffffffffffffffffffff16637dccab6683836040518363ffffffff1660e01b8152600401610190929190610349565b5f604051808303815f87803b1580156101a7575f80fd5b505af11580156101b9573d5f803e3d5ffd5b505050505050565b5f825c90508181036101fe577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610236565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd98160405161022d9190610370565b60405180910390a15b505050565b5f81835d825c905081810361027b577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16102b3565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9816040516102aa9190610370565b60405180910390a15b505050565b6101b28061038a83390190565b5f80fd5b5f819050919050565b6102db816102c9565b81146102e5575f80fd5b50565b5f813590506102f6816102d2565b92915050565b5f8060408385031215610312576103116102c5565b5b5f61031f858286016102e8565b9250506020610330858286016102e8565b9150509250929050565b610343816102c9565b82525050565b5f60408201905061035c5f83018561033a565b610369602083018461033a565b9392505050565b5f6020820190506103835f83018461033a565b9291505056fe6080604052348015600e575f80fd5b506101968061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80637dccab661461002d575b5f80fd5b610047600480360381019061004291906100fa565b610049565b005b5f825c9050818103610086577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100be565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9816040516100b59190610147565b60405180910390a15b505050565b5f80fd5b5f819050919050565b6100d9816100c7565b81146100e3575f80fd5b50565b5f813590506100f4816100d0565b92915050565b5f80604083850312156101105761010f6100c3565b5b5f61011d858286016100e6565b925050602061012e858286016100e6565b9150509250929050565b610141816100c7565b82525050565b5f60208201905061015a5f830184610138565b9291505056fea2646970667358221220299e78f210bb50b25e55a7d3d761eb697663f501d6b877c5f17e651d5c7111fb64736f6c634300081a0033a2646970667358221220d99f2c2087ad3b0f2283262f95bb66f6becb8b8538af83c1a9a571716f0abb1b64736f6c634300081a0033 + +TestTransientStorageOtherContract: 6080604052348015600e575f80fd5b506101968061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80637dccab661461002d575b5f80fd5b610047600480360381019061004291906100fa565b610049565b005b5f825c9050818103610086577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100be565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9816040516100b59190610147565b60405180910390a15b505050565b5f80fd5b5f819050919050565b6100d9816100c7565b81146100e3575f80fd5b50565b5f813590506100f4816100d0565b92915050565b5f80604083850312156101105761010f6100c3565b5b5f61011d858286016100e6565b925050602061012e858286016100e6565b9150509250929050565b610141816100c7565b82525050565b5f60208201905061015a5f830184610138565b9291505056fea2646970667358221220299e78f210bb50b25e55a7d3d761eb697663f501d6b877c5f17e651d5c7111fb64736f6c634300081a0033 + +// CONTRACT CALLS + +TestTransientStorage: + + 7dccab66: checkDataEqualsTheValuePassed(bytes32,bytes32) + 7b70ef4e: checkIfNestedTransactionFromOtherContractShareMemory(bytes32,bytes32) + 5dbdd0ce: checkIfNestedTransactionSameContractShareMemory(bytes32,bytes32) + f5cc67a1: checkTransientStorage(bytes32,bytes32) + +TestTransientStorageOtherContract: +- 7dccab66 -> checkDataEqualsTheValuePassed(bytes32,bytes32) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TestTransientStorage contract +transaction_build txTestTransientStorageContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f80fd5b506105718061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80635dbdd0ce1461004e5780637b70ef4e1461006a5780637dccab6614610086578063f5cc67a1146100a2575b5f80fd5b610068600480360381019061006391906102fc565b6100be565b005b610084600480360381019061007f91906102fc565b61012d565b005b6100a0600480360381019061009b91906102fc565b6101c1565b005b6100bc60048036038101906100b791906102fc565b61023b565b005b80825d3073ffffffffffffffffffffffffffffffffffffffff16637dccab6683836040518363ffffffff1660e01b81526004016100fc929190610349565b5f604051808303815f87803b158015610113575f80fd5b505af1158015610125573d5f803e3d5ffd5b505050505050565b80825d60405161013c906102b8565b604051809103905ff080158015610155573d5f803e3d5ffd5b5073ffffffffffffffffffffffffffffffffffffffff16637dccab6683836040518363ffffffff1660e01b8152600401610190929190610349565b5f604051808303815f87803b1580156101a7575f80fd5b505af11580156101b9573d5f803e3d5ffd5b505050505050565b5f825c90508181036101fe577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610236565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd98160405161022d9190610370565b60405180910390a15b505050565b5f81835d825c905081810361027b577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16102b3565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9816040516102aa9190610370565b60405180910390a15b505050565b6101b28061038a83390190565b5f80fd5b5f819050919050565b6102db816102c9565b81146102e5575f80fd5b50565b5f813590506102f6816102d2565b92915050565b5f8060408385031215610312576103116102c5565b5b5f61031f858286016102e8565b9250506020610330858286016102e8565b9150509250929050565b610343816102c9565b82525050565b5f60408201905061035c5f83018561033a565b610369602083018461033a565b9392505050565b5f6020820190506103835f83018461033a565b9291505056fe6080604052348015600e575f80fd5b506101968061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80637dccab661461002d575b5f80fd5b610047600480360381019061004291906100fa565b610049565b005b5f825c9050818103610086577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100be565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9816040516100b59190610147565b60405180910390a15b505050565b5f80fd5b5f819050919050565b6100d9816100c7565b81146100e3575f80fd5b50565b5f813590506100f4816100d0565b92915050565b5f80604083850312156101105761010f6100c3565b5b5f61011d858286016100e6565b925050602061012e858286016100e6565b9150509250929050565b610141816100c7565b82525050565b5f60208201905061015a5f830184610138565b9291505056fea2646970667358221220299e78f210bb50b25e55a7d3d761eb697663f501d6b877c5f17e651d5c7111fb64736f6c634300081a0033a2646970667358221220d99f2c2087ad3b0f2283262f95bb66f6becb8b8538af83c1a9a571716f0abb1b64736f6c634300081a0033 + gas 1000000 + build + +# Create block to hold txTestTransientStorageContract transaction +block_build b01 + parent g00 + transactions txTestTransientStorageContract + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to deploy TestTransientStorageOtherContract contract +transaction_build txTestTransientStorageOtherContract + sender acc1 + nonce 1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f80fd5b506101968061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80637dccab661461002d575b5f80fd5b610047600480360381019061004291906100fa565b610049565b005b5f825c9050818103610086577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16100be565b7f2fe0d3bd8bbb632441eefda46ec52f1ddda3a9e827d14c40f422037320f28bd9816040516100b59190610147565b60405180910390a15b505050565b5f80fd5b5f819050919050565b6100d9816100c7565b81146100e3575f80fd5b50565b5f813590506100f4816100d0565b92915050565b5f80604083850312156101105761010f6100c3565b5b5f61011d858286016100e6565b925050602061012e858286016100e6565b9150509250929050565b610141816100c7565b82525050565b5f60208201905061015a5f830184610138565b9291505056fea2646970667358221220299e78f210bb50b25e55a7d3d761eb697663f501d6b877c5f17e651d5c7111fb64736f6c634300081a0033 + gas 1000000 + build + +# Create block to hold txTestTransientStorageOtherContract transaction +block_build b02 + parent b01 + transactions txTestTransientStorageOtherContract + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 + +# Create transaction to execute checkTransientStorage(bytes32 key, bytes32 value) method +transaction_build txTestTransientStorageOpCodes + sender acc1 + nonce 2 + contract txTestTransientStorageContract + value 0 + data f5cc67a131000000000000000000000000000000000000000000000000000000000000003200000000000000000000000000000000000000000000000000000000000000 + gas 200000 + build + +# Create block to hold txTestTransientStorageOpCodes transaction +block_build b03 + parent b02 + transactions txTestTransientStorageOpCodes + gasLimit 350000 + build + +# Connect block +block_connect b03 + +# Check b02 is best block +assert_best b03 + +# Create transaction to execute checkTransientStorage(bytes32 key, bytes32 value) method +transaction_build txTestTransientStorageOpCodesOtherValue + sender acc1 + nonce 3 + contract txTestTransientStorageContract + value 0 + data f5cc67a132000000000000000000000000000000000000000000000000000000000000003132333435000000000000000000000000000000000000000000000000000000 + gas 200000 + build + +# Create block to hold txTestTransientStorageOpCodesOtherValue transaction +block_build b04 + parent b03 + transactions txTestTransientStorageOpCodesOtherValue + gasLimit 350000 + build + +# Connect block +block_connect b04 + +# Check b02 is best block +assert_best b04 + +# Create transaction to execute checkIfNestedTransactionSameContractShareMemory(bytes32 key, bytes32 value) method +transaction_build txTestTransientStorageNestedTransactionShareMemory + sender acc1 + nonce 4 + contract txTestTransientStorageContract + value 0 + data f5cc67a131300000000000000000000000000000000000000000000000000000000000003230000000000000000000000000000000000000000000000000000000000000 + gas 200000 + build + +# Create block to hold txTestTransientStorageNestedTransactionShareMemory transaction +block_build b05 + parent b04 + transactions txTestTransientStorageNestedTransactionShareMemory + gasLimit 350000 + build + +# Connect block +block_connect b05 + +# Check b02 is best block +assert_best b05 + +# Create transaction to execute checkIfNestedTransactionFromOtherContractShareMemory(bytes32 key, bytes32 value) method +transaction_build txTestTransientStorageNestedTransactionOtherContractDoesntShareMemory + sender acc1 + nonce 5 + contract txTestTransientStorageContract + value 0 + data 7b70ef4e31300000000000000000000000000000000000000000000000000000000000003230000000000000000000000000000000000000000000000000000000000000 + gas 200000 + build + +# Create block to hold txTestTransientStorageNestedTransactionOtherContractDoesntShareMemory transaction +block_build b06 + parent b05 + transactions txTestTransientStorageNestedTransactionOtherContractDoesntShareMemory + gasLimit 350000 + build + +# Connect block +block_connect b06 + +# Check b02 is best block +assert_best b06 + diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_tstore_checking_between_transactions.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_tstore_checking_between_transactions.txt new file mode 100644 index 00000000000..f71eb82d0a2 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tload_tstore_checking_between_transactions.txt @@ -0,0 +1,116 @@ +comment + +// CONTRACT CODE +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +contract TloadTstoreCheckingBetweenTransactions { + constructor() { + } + + event OK(); + event ERROR(string, uint256); + event ValueStored(uint256 key, uint256 value); + event ValueLoaded(uint256 key, uint256 value); + + // Function to test TSTORE some value + function tstoreAndTloadSomeValue(uint256 key, uint256 value) external { + uint256 loadedValue; + assembly { + // Store a value in transient storage + tstore(key, value) + } + emit ValueStored(key, value); + + assembly { + // Load the value from transient storage + loadedValue := tload(key) + } + emit ValueLoaded(key, loadedValue); + } + + // Function to test TSTORE some value + function tloadSomeValueAndCheckWithExpected(uint256 key, uint256 valueExpected) external { + uint256 loadedValue; + assembly { + // Load the value from transient storage + loadedValue := tload(key) + } + emit ValueLoaded(key, loadedValue); + if (loadedValue == valueExpected) { + emit OK(); + } else { + emit ERROR('Value loaded is different from the expected',loadedValue); + } + } +} + +// CONTRACT BYTECODE + +TloadTstoreCheckingBetweenTransactions: 6080604052348015600e575f5ffd5b5061032f8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c806398c051f414610038578063a042e69514610054575b5f5ffd5b610052600480360381019061004d91906101d9565b610070565b005b61006e600480360381019061006991906101d9565b6100ef565b005b5f81835d7f310f8ed862379d5c76886cc6d311ff93d07260f8609687c75d38a3916f469b5583836040516100a5929190610226565b60405180910390a1825c90507f9852f8e8d49fd9a2e49e060d8d3b08d73a4cad92444150877509d7ab57f2e5ef83826040516100e2929190610226565b60405180910390a1505050565b5f825c90507f9852f8e8d49fd9a2e49e060d8d3b08d73a4cad92444150877509d7ab57f2e5ef8382604051610125929190610226565b60405180910390a1818103610165577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161019d565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8160405161019491906102cd565b60405180910390a15b505050565b5f5ffd5b5f819050919050565b6101b8816101a6565b81146101c2575f5ffd5b50565b5f813590506101d3816101af565b92915050565b5f5f604083850312156101ef576101ee6101a2565b5b5f6101fc858286016101c5565b925050602061020d858286016101c5565b9150509250929050565b610220816101a6565b82525050565b5f6040820190506102395f830185610217565b6102466020830184610217565b9392505050565b5f82825260208201905092915050565b7f56616c7565206c6f6164656420697320646966666572656e742066726f6d20745f8201527f6865206578706563746564000000000000000000000000000000000000000000602082015250565b5f6102b7602b8361024d565b91506102c28261025d565b604082019050919050565b5f6040820190508181035f8301526102e4816102ab565b90506102f36020830184610217565b9291505056fea2646970667358221220433294a89265547198272c5831a9646c55777d997ff5f31e3d70a38fb431c2ea64736f6c634300081c0033 + +// CONTRACT CALLS + +TloadTstoreCheckingBetweenTransactions: + +- a042e695: tloadSomeValueAndCheckWithExpected(uint256,uint256) +- 98c051f4: tstoreAndTloadSomeValue(uint256,uint256) + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TloadTstoreCheckingBetweenTransactions contract +transaction_build txTloadTstoreCheckingBetweenTransactionsContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f5ffd5b5061032f8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c806398c051f414610038578063a042e69514610054575b5f5ffd5b610052600480360381019061004d91906101d9565b610070565b005b61006e600480360381019061006991906101d9565b6100ef565b005b5f81835d7f310f8ed862379d5c76886cc6d311ff93d07260f8609687c75d38a3916f469b5583836040516100a5929190610226565b60405180910390a1825c90507f9852f8e8d49fd9a2e49e060d8d3b08d73a4cad92444150877509d7ab57f2e5ef83826040516100e2929190610226565b60405180910390a1505050565b5f825c90507f9852f8e8d49fd9a2e49e060d8d3b08d73a4cad92444150877509d7ab57f2e5ef8382604051610125929190610226565b60405180910390a1818103610165577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a161019d565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8160405161019491906102cd565b60405180910390a15b505050565b5f5ffd5b5f819050919050565b6101b8816101a6565b81146101c2575f5ffd5b50565b5f813590506101d3816101af565b92915050565b5f5f604083850312156101ef576101ee6101a2565b5b5f6101fc858286016101c5565b925050602061020d858286016101c5565b9150509250929050565b610220816101a6565b82525050565b5f6040820190506102395f830185610217565b6102466020830184610217565b9392505050565b5f82825260208201905092915050565b7f56616c7565206c6f6164656420697320646966666572656e742066726f6d20745f8201527f6865206578706563746564000000000000000000000000000000000000000000602082015250565b5f6102b7602b8361024d565b91506102c28261025d565b604082019050919050565b5f6040820190508181035f8301526102e4816102ab565b90506102f36020830184610217565b9291505056fea2646970667358221220433294a89265547198272c5831a9646c55777d997ff5f31e3d70a38fb431c2ea64736f6c634300081c0033 + gas 1000000 + build + +# Create block to hold txTloadTstoreCheckingBetweenTransactionsContract transaction +block_build b01 + parent g00 + transactions txTloadTstoreCheckingBetweenTransactionsContract + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute +transaction_build txTstoreAndTloadSomeValue + sender acc1 + nonce 1 + contract txTloadTstoreCheckingBetweenTransactionsContract + value 0 + data 98c051f400000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000064 + gas 200000 + build + +# Create transaction to execute +transaction_build txTloadSomeValueAndCheckWithExpected + sender acc1 + nonce 2 + contract txTloadTstoreCheckingBetweenTransactionsContract + value 0 + data a042e69500000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000 + gas 200000 + build + +# Create block to hold txTloadSomeValueAndCheckWithExpected transaction +block_build b02 + parent b01 + transactions txTstoreAndTloadSomeValue txTloadSomeValueAndCheckWithExpected + gasLimit 500000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstorage_gas_measure_tests.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstorage_gas_measure_tests.txt new file mode 100644 index 00000000000..c560ad5aef6 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstorage_gas_measure_tests.txt @@ -0,0 +1,126 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TstorageGasMeasureTestCases { + uint public gasUsed; + + constructor() + { + + } + + event OK(); + event ERROR(string, uint256); + + function checkGasMeasures() external { + // Checking tload gas cost + uint gasBefore; + uint gasAfter; + assembly { + gasBefore := gas() + let value := tload(0x10) + gasAfter := gas() + } + gasUsed = gasBefore - gasAfter; + checkReturnValueExpected(gasUsed, 'Checking tload gas spent is the expected', 110); + + // Checking tstore and tload gas cost + assembly { + gasBefore := gas() + tstore(0x10, 0x10) + let value := tload(0x10) + gasAfter := gas() + } + gasUsed = gasBefore - gasAfter; + checkReturnValueExpected(gasUsed, 'Checking tstore and tload gas spent is the expected', 216); + + // Checking tstore in a cold slot + assembly { + gasBefore := gas() + tstore(0xFF, 0x10) + gasAfter := gas() + } + gasUsed = gasBefore - gasAfter; + checkReturnValueExpected(gasUsed, 'Checking tstore cold gas spent is the expected', 113); + + // Checking tstore warm + assembly { + gasBefore := gas() + tstore(0xFF, 0x10) + tstore(0xFF, 0x11) + gasAfter := gas() + } + gasUsed = gasBefore - gasAfter; + checkReturnValueExpected(gasUsed, 'Checking tstore warm gas spent is the expected', 219); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} +// DESCRIPTION + +// CONTRACT BYTECODE + +TstorageGasMeasureTestCases: 6080604052348015600e575f5ffd5b506104098061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c806307e5ab1e14610038578063592cdadd14610042575b5f5ffd5b610040610060565b005b61004a610171565b6040516100579190610205565b60405180910390f35b5f5f5a915060105c5a9150508082610078919061024b565b5f819055506100a25f5460405180606001604052806028815260200161037e60289139606e610176565b5a91506010805d60105c5a91505080826100bc919061024b565b5f819055506100e65f5460405180606001604052806033815260200161034b6033913960d8610176565b5a9150601060ff5d5a905080826100fd919061024b565b5f819055506101275f546040518060600160405280602e81526020016103a6602e91396071610176565b5a9150601060ff5d601160ff5d5a90508082610143919061024b565b5f8190555061016d5f546040518060600160405280602e815260200161031d602e913960db610176565b5050565b5f5481565b8083036101ae577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101e8565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516101df9291906102ee565b60405180910390a15b505050565b5f819050919050565b6101ff816101ed565b82525050565b5f6020820190506102185f8301846101f6565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610255826101ed565b9150610260836101ed565b92508282039050818111156102785761027761021e565b5b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102c08261027e565b6102ca8185610288565b93506102da818560208601610298565b6102e3816102a6565b840191505092915050565b5f6040820190508181035f83015261030681856102b6565b905061031560208301846101f6565b939250505056fe436865636b696e67207473746f7265207761726d20676173207370656e7420697320746865206578706563746564436865636b696e67207473746f726520616e6420746c6f616420676173207370656e7420697320746865206578706563746564436865636b696e6720746c6f616420676173207370656e7420697320746865206578706563746564436865636b696e67207473746f726520636f6c6420676173207370656e7420697320746865206578706563746564a2646970667358221220b17e2b2108ab28708c0fb481438a67aaae5b4c10a6e07af3125fe9d609eb498c64736f6c634300081c0033 + +function hashes: + +- 07e5ab1e: checkGasMeasures() +- 592cdadd: gasUsed() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstorageGasMeasureTestCases contract +transaction_build txTstorageGasMeasureTestContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f5ffd5b506104098061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c806307e5ab1e14610038578063592cdadd14610042575b5f5ffd5b610040610060565b005b61004a610171565b6040516100579190610205565b60405180910390f35b5f5f5a915060105c5a9150508082610078919061024b565b5f819055506100a25f5460405180606001604052806028815260200161037e60289139606e610176565b5a91506010805d60105c5a91505080826100bc919061024b565b5f819055506100e65f5460405180606001604052806033815260200161034b6033913960d8610176565b5a9150601060ff5d5a905080826100fd919061024b565b5f819055506101275f546040518060600160405280602e81526020016103a6602e91396071610176565b5a9150601060ff5d601160ff5d5a90508082610143919061024b565b5f8190555061016d5f546040518060600160405280602e815260200161031d602e913960db610176565b5050565b5f5481565b8083036101ae577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a16101e8565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f82846040516101df9291906102ee565b60405180910390a15b505050565b5f819050919050565b6101ff816101ed565b82525050565b5f6020820190506102185f8301846101f6565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610255826101ed565b9150610260836101ed565b92508282039050818111156102785761027761021e565b5b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6102c08261027e565b6102ca8185610288565b93506102da818560208601610298565b6102e3816102a6565b840191505092915050565b5f6040820190508181035f83015261030681856102b6565b905061031560208301846101f6565b939250505056fe436865636b696e67207473746f7265207761726d20676173207370656e7420697320746865206578706563746564436865636b696e67207473746f726520616e6420746c6f616420676173207370656e7420697320746865206578706563746564436865636b696e6720746c6f616420676173207370656e7420697320746865206578706563746564436865636b696e67207473746f726520636f6c6420676173207370656e7420697320746865206578706563746564a2646970667358221220b17e2b2108ab28708c0fb481438a67aaae5b4c10a6e07af3125fe9d609eb498c64736f6c634300081c0033 + gas 1000000 + build + +# Create block to hold txTstorageGasMeasureTestContract transaction +block_build b01 + parent g00 + transactions txTstorageGasMeasureTestContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txCheckGasMeasures function +transaction_build txCheckGasMeasures + sender acc1 + nonce 1 + contract txTstorageGasMeasureTestContract + value 0 + data 07e5ab1e + gas 350000 + build + +# Create block to hold txCheckGasMeasures transaction +block_build b02 + parent b01 + transactions txCheckGasMeasures + gasLimit 400000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_after_selfdestruct_new_contract.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_after_selfdestruct_new_contract.txt new file mode 100644 index 00000000000..7902b36f366 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_after_selfdestruct_new_contract.txt @@ -0,0 +1,146 @@ +comment + +// CONTRACT CODE + +pragma solidity ^0.8.24; + +contract TstoreAfterSelfdestructingNewContract { + + constructor() { + } + + event OK(); + event ERROR(string, uint256); + + function performtTest() external { + Callee callee = new Callee(); + address calleeAddress = address(callee); + uint256 resultCallOption1; + uint256 resultCallOption2; + uint256 resultCallOption3; + uint256 valueLoadedFromMemory; + bytes4 executeSignature = bytes4(keccak256("execute(uint256)")); + + assembly { + // Call Option 1: Executes selfdestruct in callee contract + let availablePointerCallOption1 := mload(0x40) + mstore(availablePointerCallOption1, executeSignature) + mstore(add(availablePointerCallOption1, 4), 1) + resultCallOption1 := call(gas(), calleeAddress, 0, availablePointerCallOption1, 0x24, availablePointerCallOption1, 0x20) + + // Call Option 2: Executes tstore in callee contract + let availablePointerCallOption2 := mload(0x40) + mstore(availablePointerCallOption2, executeSignature) + mstore(add(availablePointerCallOption2, 4), 2) + resultCallOption2 := call(gas(), calleeAddress, 0, availablePointerCallOption2, 0x24, availablePointerCallOption2, 0x20) + + + // Call Option 3: Executes tload, store it in memory and return data + let availablePointerCallOption3 := mload(0x40) + mstore(availablePointerCallOption3, executeSignature) + mstore(add(availablePointerCallOption3, 4), 3) + resultCallOption3 := call(gas(), calleeAddress, 0, availablePointerCallOption3, 0x24, availablePointerCallOption3, 0x20) + + // Copy returndata into memory to retrieve the returned value + returndatacopy(availablePointerCallOption3, 0, returndatasize()) + valueLoadedFromMemory := mload(availablePointerCallOption3) + } + + checkReturnValueExpected(resultCallOption1, 'Checking result call option 1', 0x01); + checkReturnValueExpected(resultCallOption2, 'Checking result call option 2', 0x01); + checkReturnValueExpected(resultCallOption3, 'Checking result call option 3', 0x01); + checkReturnValueExpected(valueLoadedFromMemory, 'Checking value from mload 0', 0x100); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + event OK(); + event ERROR(string, uint256); + + function execute(uint256 callOption) external returns (uint256) { + assembly { + switch callOption + case 1 { + selfdestruct(0) + } + case 2 { + tstore(0xFF, 0x100) + } + case 3 { + // Load value from transient storage + let value := tload(0xFF) + mstore(0x00, value) // Store it in memory to return + return(0x00, 0x20) // Return 32 bytes from memory + } + } + } +} + +// DESCRIPTION + +// CONTRACT BYTECODE + +TstoreAfterSelfdestructingNewContract: 608060405234801561000f575f80fd5b506104f28061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f60405161004490610267565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f8190505f805f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f8b5af19550604051828152600260048201526020816024835f8c5af19550604051838152600360048201526020816024835f8d5af195503d5f823e80519450505050610123856040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203100000081525060016101f0565b610164846040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203200000081525060016101f0565b6101a5836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203300000081525060016101f0565b6101e7826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f6164203000000000008152506101006101f0565b50505050505050565b808303610228577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610262565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610259929190610316565b60405180910390a15b505050565b6101788061034583390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156102ab578082015181840152602081019050610290565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6102d082610274565b6102da818561027e565b93506102ea81856020860161028e565b6102f3816102b6565b840191505092915050565b5f819050919050565b610310816102fe565b82525050565b5f6040820190508181035f83015261032e81856102c6565b905061033d6020830184610307565b939250505056fe608060405234801561000f575f80fd5b5061015b8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b610047600480360381019061004291906100d2565b61005d565b604051610054919061010c565b60405180910390f35b5f816001811461007c576002811461007f576003811461008a57610095565b5fff5b61010060ff5d610095565b60ff5c805f5260205ff35b50919050565b5f80fd5b5f819050919050565b6100b18161009f565b81146100bb575f80fd5b50565b5f813590506100cc816100a8565b92915050565b5f602082840312156100e7576100e661009b565b5b5f6100f4848285016100be565b91505092915050565b6101068161009f565b82525050565b5f60208201905061011f5f8301846100fd565b9291505056fea264697066735822122052a1869c2ba9a2749479c068cda41ba0a57aa6967098ab6a0fdc351722448d5d64736f6c63430008180033a264697066735822122004e2a48494b3e22b144f5f63708a43173ddd8cff969f549ce7636f99245196da64736f6c63430008180033 + +function hashes: + +- 0d0b85f1: performTest() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TloadAfterSelfdestructPreExistingContract contract +transaction_build txDeployTestContract + sender acc1 + receiverAddress 00 + value 0 + data 608060405234801561000f575f80fd5b506104f28061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f60405161004490610267565b604051809103905ff08015801561005d573d5f803e3d5ffd5b5090505f8190505f805f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f8b5af19550604051828152600260048201526020816024835f8c5af19550604051838152600360048201526020816024835f8d5af195503d5f823e80519450505050610123856040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203100000081525060016101f0565b610164846040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203200000081525060016101f0565b6101a5836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203300000081525060016101f0565b6101e7826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f6164203000000000008152506101006101f0565b50505050505050565b808303610228577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610262565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f8284604051610259929190610316565b60405180910390a15b505050565b6101788061034583390190565b5f81519050919050565b5f82825260208201905092915050565b5f5b838110156102ab578082015181840152602081019050610290565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6102d082610274565b6102da818561027e565b93506102ea81856020860161028e565b6102f3816102b6565b840191505092915050565b5f819050919050565b610310816102fe565b82525050565b5f6040820190508181035f83015261032e81856102c6565b905061033d6020830184610307565b939250505056fe608060405234801561000f575f80fd5b5061015b8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b610047600480360381019061004291906100d2565b61005d565b604051610054919061010c565b60405180910390f35b5f816001811461007c576002811461007f576003811461008a57610095565b5fff5b61010060ff5d610095565b60ff5c805f5260205ff35b50919050565b5f80fd5b5f819050919050565b6100b18161009f565b81146100bb575f80fd5b50565b5f813590506100cc816100a8565b92915050565b5f602082840312156100e7576100e661009b565b5b5f6100f4848285016100be565b91505092915050565b6101068161009f565b82525050565b5f60208201905061011f5f8301846100fd565b9291505056fea264697066735822122052a1869c2ba9a2749479c068cda41ba0a57aa6967098ab6a0fdc351722448d5d64736f6c63430008180033a264697066735822122004e2a48494b3e22b144f5f63708a43173ddd8cff969f549ce7636f99245196da64736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txDeployTestContract transaction +block_build b01 + parent g00 + transactions txDeployTestContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute performTest function from contract +transaction_build txPerformTest + sender acc1 + nonce 1 + contract txDeployTestContract + value 0 + data 0d0b85f1 + gas 300000 + build + +# Create block to hold txPerformTest transaction +block_build b02 + parent b01 + transactions txPerformTest + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_after_selfdestruct_pre_existing_contract.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_after_selfdestruct_pre_existing_contract.txt new file mode 100644 index 00000000000..3766de47657 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_after_selfdestruct_pre_existing_contract.txt @@ -0,0 +1,147 @@ +comment + +// CONTRACT CODE + +pragma solidity ^0.8.24; + +contract TstoreAfterSelfdestructingPreExistingContract { + Callee callee; + + constructor() { + callee = new Callee(); + } + + event OK(); + event ERROR(string, uint256); + + function performTest() external { + address calleeAddress = address(callee); + uint256 resultCallOption1; + uint256 resultCallOption2; + uint256 resultCallOption3; + uint256 valueLoadedFromMemory; + bytes4 executeSignature = bytes4(keccak256("execute(uint256)")); + + assembly { + // Call Option 1: Executes selfdestruct in callee contract + let availablePointerCallOption1 := mload(0x40) + mstore(availablePointerCallOption1, executeSignature) + mstore(add(availablePointerCallOption1, 4), 1) + resultCallOption1 := call(gas(), calleeAddress, 0, availablePointerCallOption1, 0x24, availablePointerCallOption1, 0x20) + + // Call Option 2: Executes tstore in callee contract + let availablePointerCallOption2 := mload(0x40) + mstore(availablePointerCallOption2, executeSignature) + mstore(add(availablePointerCallOption2, 4), 2) + resultCallOption2 := call(gas(), calleeAddress, 0, availablePointerCallOption2, 0x24, availablePointerCallOption2, 0x20) + + + // Call Option 3: Executes tload, store it in memory and return data + let availablePointerCallOption3 := mload(0x40) + mstore(availablePointerCallOption3, executeSignature) + mstore(add(availablePointerCallOption3, 4), 3) + resultCallOption3 := call(gas(), calleeAddress, 0, availablePointerCallOption3, 0x24, availablePointerCallOption3, 0x20) + + // Copy returndata into memory to retrieve the returned value + returndatacopy(availablePointerCallOption3, 0, returndatasize()) + valueLoadedFromMemory := mload(availablePointerCallOption3) + } + + checkReturnValueExpected(resultCallOption1, 'Checking result call option 1', 0x01); + checkReturnValueExpected(resultCallOption2, 'Checking result call option 2', 0x01); + checkReturnValueExpected(resultCallOption3, 'Checking result call option 3', 0x01); + checkReturnValueExpected(valueLoadedFromMemory, 'Checking value from mload 0', 0x100); + } + + function checkReturnValueExpected(uint256 valueReceived, string memory message, uint256 expectedValue) private { + if( valueReceived == expectedValue){ + emit OK(); + } else { + emit ERROR(message, valueReceived); + } + } +} + +contract Callee { + + event OK(); + event ERROR(string, uint256); + + function execute(uint256 callOption) external returns (uint256) { + assembly { + switch callOption + case 1 { + selfdestruct(0) + } + case 2 { + tstore(0xFF, 0x100) + } + case 3 { + // Load value from transient storage + let value := tload(0xFF) + mstore(0x00, value) // Store it in memory to return + return(0x00, 0x20) // Return 32 bytes from memory + } + } + } +} + +// DESCRIPTION + +// CONTRACT BYTECODE + +TstoreAfterSelfdestructingPreExistingContract: 608060405234801561000f575f80fd5b5060405161001c90610079565b604051809103905ff080158015610035573d5f803e3d5ffd5b505f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610086565b610178806103f683390190565b610363806100935f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f8b5af19550604051828152600260048201526020816024835f8c5af19550604051838152600360048201526020816024835f8d5af195503d5f823e8051945050505061011a856040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203100000081525060016101e6565b61015b846040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203200000081525060016101e6565b61019c836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203300000081525060016101e6565b6101de826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f6164203000000000008152506101006101e6565b505050505050565b80830361021e577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610258565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161024f9291906102ff565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610294578082015181840152602081019050610279565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6102b98261025d565b6102c38185610267565b93506102d3818560208601610277565b6102dc8161029f565b840191505092915050565b5f819050919050565b6102f9816102e7565b82525050565b5f6040820190508181035f83015261031781856102af565b905061032660208301846102f0565b939250505056fea2646970667358221220430065adaea3ec55b26991f3b100cb73215160e30134979bc834001868b7049464736f6c63430008180033608060405234801561000f575f80fd5b5061015b8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b610047600480360381019061004291906100d2565b61005d565b604051610054919061010c565b60405180910390f35b5f816001811461007c576002811461007f576003811461008a57610095565b5fff5b61010060ff5d610095565b60ff5c805f5260205ff35b50919050565b5f80fd5b5f819050919050565b6100b18161009f565b81146100bb575f80fd5b50565b5f813590506100cc816100a8565b92915050565b5f602082840312156100e7576100e661009b565b5b5f6100f4848285016100be565b91505092915050565b6101068161009f565b82525050565b5f60208201905061011f5f8301846100fd565b9291505056fea26469706673582212202863e4706ef82faa6ad13fcf9e1ee1699e2008d0c74aa076910f6421a8bacd5b64736f6c63430008180033 + +function hashes: + +- 0d0b85f1: performTest() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TloadAfterSelfdestructPreExistingContract contract +transaction_build txDeployTestContract + sender acc1 + receiverAddress 00 + value 0 + data 608060405234801561000f575f80fd5b5060405161001c90610079565b604051809103905ff080158015610035573d5f803e3d5ffd5b505f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610086565b610178806103f683390190565b610363806100935f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80630d0b85f11461002d575b5f80fd5b610035610037565b005b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505f805f805f7ffe0d94c1a8f5608a1172c49cc7704ac011b690506896af15ba9aab651ff44e1b9050604051818152600160048201526020816024835f8b5af19550604051828152600260048201526020816024835f8c5af19550604051838152600360048201526020816024835f8d5af195503d5f823e8051945050505061011a856040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203100000081525060016101e6565b61015b846040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203200000081525060016101e6565b61019c836040518060400160405280601d81526020017f436865636b696e6720726573756c742063616c6c206f7074696f6e203300000081525060016101e6565b6101de826040518060400160405280601b81526020017f436865636b696e672076616c75652066726f6d206d6c6f6164203000000000008152506101006101e6565b505050505050565b80830361021e577fd48fe2800bace8f5ca2450feacbd6efc681b1cd0115019bb49fa529b6171bf6760405160405180910390a1610258565b7fc9e730d5b570f89e168eb8c3d29f8c396b957e540af248c95c9519ac47c2c69f828460405161024f9291906102ff565b60405180910390a15b505050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610294578082015181840152602081019050610279565b5f8484015250505050565b5f601f19601f8301169050919050565b5f6102b98261025d565b6102c38185610267565b93506102d3818560208601610277565b6102dc8161029f565b840191505092915050565b5f819050919050565b6102f9816102e7565b82525050565b5f6040820190508181035f83015261031781856102af565b905061032660208301846102f0565b939250505056fea2646970667358221220430065adaea3ec55b26991f3b100cb73215160e30134979bc834001868b7049464736f6c63430008180033608060405234801561000f575f80fd5b5061015b8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063fe0d94c11461002d575b5f80fd5b610047600480360381019061004291906100d2565b61005d565b604051610054919061010c565b60405180910390f35b5f816001811461007c576002811461007f576003811461008a57610095565b5fff5b61010060ff5d610095565b60ff5c805f5260205ff35b50919050565b5f80fd5b5f819050919050565b6100b18161009f565b81146100bb575f80fd5b50565b5f813590506100cc816100a8565b92915050565b5f602082840312156100e7576100e661009b565b5b5f6100f4848285016100be565b91505092915050565b6101068161009f565b82525050565b5f60208201905061011f5f8301846100fd565b9291505056fea26469706673582212202863e4706ef82faa6ad13fcf9e1ee1699e2008d0c74aa076910f6421a8bacd5b64736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txDeployTestContract transaction +block_build b01 + parent g00 + transactions txDeployTestContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute performTest function from contract +transaction_build txPerformTest + sender acc1 + nonce 1 + contract txDeployTestContract + value 0 + data 0d0b85f1 + gas 300000 + build + +# Create block to hold txPerformTest transaction +block_build b02 + parent b01 + transactions txPerformTest + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_and_tload_loop_until_out_of_gas.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_and_tload_loop_until_out_of_gas.txt new file mode 100644 index 00000000000..2ab80ad6cea --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_and_tload_loop_until_out_of_gas.txt @@ -0,0 +1,84 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TstoreAndTloadLoopUntilOutOfGas { + + constructor() + { + + } + + function runTstoreAndTloadUntilOutOfGas() external { + // Run tstore and tload in loop until out of gas + for (uint256 i = 0; i < 1000000; i++) { + assembly { + let gasValue := gas() + tstore(gasValue, gas()) + let loadedValue := tload(gasValue) + pop(0) + } + } + } +} + +// DESCRIPTION + +// CONTRACT BYTECODE + +TstoreAndTloadLoopUntilOutOfGas: 6080604052348015600e575f80fd5b5060888061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063ae1978d714602a575b5f80fd5b60306032565b005b5f5b620f4240811015604f575a5a815d5080806001019150506034565b5056fea2646970667358221220db37ed7fb5e1de866d127a5da76e02d895a6014e4de7965e57f66ae94ad5d1d764736f6c63430008180033 + +function hashes: + +- ae1978d7: runTstoreAndTloadUntilOutOfGas() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstoreWideAddressSpaceLoopUntilOutOfGas contract +transaction_build txTstoreAndTloadLoopUntilOutOfGasContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f80fd5b5060888061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c8063ae1978d714602a575b5f80fd5b60306032565b005b5f5b620f4240811015604f575a5a815d5080806001019150506034565b5056fea2646970667358221220db37ed7fb5e1de866d127a5da76e02d895a6014e4de7965e57f66ae94ad5d1d764736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txTstoreAndTloadLoopUntilOutOfGasContract transaction +block_build b01 + parent g00 + transactions txTstoreAndTloadLoopUntilOutOfGasContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txRunTstoreUntilOutOfGas function +transaction_build txRunTstoreAndTloadUntilOutOfGas + sender acc1 + nonce 1 + contract txTstoreAndTloadLoopUntilOutOfGasContract + value 0 + data ae1978d7 + gas 700000 + build + +# Create block to hold txRunTstoreAndTloadUntilOutOfGas transaction +block_build b02 + parent b01 + transactions txRunTstoreAndTloadUntilOutOfGas + gasLimit 750000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_loop_until_out_of_gas.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_loop_until_out_of_gas.txt new file mode 100644 index 00000000000..62d3361b6bd --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_loop_until_out_of_gas.txt @@ -0,0 +1,79 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TstoreLoopUntilOutOfGas { + + constructor() + { + } + + function runTstoreUntilOutOfGas() external { + // Run tstore in loop until out of gas + for (uint256 i = 0; i < 1000000; i++) { + assembly { + tstore(gas(), gas()) + } + } + } +} +// DESCRIPTION + +// CONTRACT BYTECODE + +TstoreLoopUntilOutOfGas: 6080604052348015600e575f80fd5b5060868061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c80637b17abde14602a575b5f80fd5b60306032565b005b5f5b620f4240811015604d575a5a5d80806001019150506034565b5056fea2646970667358221220460f7f44d313897b5627f933b4969a97d228645b5447a4ea286119f6cc66155964736f6c63430008180033 + +function hashes: + +- 7b17abde: runTstoreUntilOutOfGas() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstoreLoopUntilOutOfGas contract +transaction_build txTstoreLoopUntilOutOfGasContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f80fd5b5060868061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c80637b17abde14602a575b5f80fd5b60306032565b005b5f5b620f4240811015604d575a5a5d80806001019150506034565b5056fea2646970667358221220460f7f44d313897b5627f933b4969a97d228645b5447a4ea286119f6cc66155964736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txTstoreLoopUntilOutOfGasContract transaction +block_build b01 + parent g00 + transactions txTstoreLoopUntilOutOfGasContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txRunTstoreUntilOutOfGas function +transaction_build txRunTstoreUntilOutOfGas + sender acc1 + nonce 1 + contract txTstoreLoopUntilOutOfGasContract + value 0 + data 7b17abde + gas 300000 + build + +# Create block to hold txRunTstoreUntilOutOfGas transaction +block_build b02 + parent b01 + transactions txRunTstoreUntilOutOfGas + gasLimit 350000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file diff --git a/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_wide_address_space_loop_until_out_of_gas.txt b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_wide_address_space_loop_until_out_of_gas.txt new file mode 100644 index 00000000000..68b0e91fba8 --- /dev/null +++ b/rskj-core/src/test/resources/dsl/transient_storage_rskip446/tstore_wide_address_space_loop_until_out_of_gas.txt @@ -0,0 +1,83 @@ +comment + +// CONTRACT CODE +pragma solidity ^0.8.24; + +contract TstoreWideAddressSpaceLoopUntilOutOfGas { + + constructor() + { + } + + function runTstoreWideAddressSpaceUntilOutOfGas() external { + // Run tstore in loop until out of gas, using a wide address space + for (uint256 i = 0; i < 1000000; i++) { + assembly { + let pcValue := codesize() + let shiftedPc := shl(pcValue, 1) + let addResult := add(shiftedPc, gas()) + tstore(addResult, gas()) + } + } + } +} + +// DESCRIPTION + +// CONTRACT BYTECODE + +TstoreWideAddressSpaceLoopUntilOutOfGas: 6080604052348015600e575f80fd5b5060918061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c806309fdcd3f14602a575b5f80fd5b60306032565b005b5f5b620f4240811015605857386001811b5a81015a815d50505080806001019150506034565b5056fea264697066735822122098cf088d672ad1d70c2d2a0edbbba6202aff9669702ae83d6e9eb1050fc6622864736f6c63430008180033 + +function hashes: + +- 09fdcd3f: runTstoreWideAddressSpaceUntilOutOfGas() + +end + +# Create and fund new account +account_new acc1 10000000 + +# Create transaction to deploy TstoreWideAddressSpaceLoopUntilOutOfGas contract +transaction_build txTstoreWideAddressSpaceLoopUntilOutOfGasContract + sender acc1 + receiverAddress 00 + value 0 + data 6080604052348015600e575f80fd5b5060918061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c806309fdcd3f14602a575b5f80fd5b60306032565b005b5f5b620f4240811015605857386001811b5a81015a815d50505080806001019150506034565b5056fea264697066735822122098cf088d672ad1d70c2d2a0edbbba6202aff9669702ae83d6e9eb1050fc6622864736f6c63430008180033 + gas 1000000 + build + +# Create block to hold txTstoreWideAddressSpaceLoopUntilOutOfGasContract transaction +block_build b01 + parent g00 + transactions txTstoreWideAddressSpaceLoopUntilOutOfGasContract + gasLimit 1200000 + build + +# Connect block +block_connect b01 + +# Check b01 is best block +assert_best b01 + +# Create transaction to execute txRunTstoreUntilOutOfGas function +transaction_build txRunTstoreWideAddressSpaceUntilOutOfGas + sender acc1 + nonce 1 + contract txTstoreWideAddressSpaceLoopUntilOutOfGasContract + value 0 + data 09fdcd3f + gas 500000 + build + +# Create block to hold txRunTstoreWideAddressSpaceUntilOutOfGas transaction +block_build b02 + parent b01 + transactions txRunTstoreWideAddressSpaceUntilOutOfGas + gasLimit 550000 + build + +# Connect block +block_connect b02 + +# Check b02 is best block +assert_best b02 \ No newline at end of file