Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
import static net.consensys.linea.reporting.TracerTestBase.chainConfig;
import static net.consensys.linea.testing.BytecodeCompiler.newProgram;

import net.consensys.linea.testing.ToyAccount;
import net.consensys.linea.zktracer.opcode.OpCode;
import org.apache.tuweni.bytes.Bytes;
import org.hyperledger.besu.datatypes.Address;

public class Utils {

public static final Bytes REVERT =
newProgram(chainConfig).push(0).push(0).op(OpCode.REVERT).compile();

Expand Down Expand Up @@ -61,4 +63,15 @@ public static Bytes delegateCall(Address address) {
.op(OpCode.DELEGATECALL)
.compile();
}

// Utils for EIP-7702 tests

public static final String DELEGATION_PREFIX = "0xef0100";

public static String addDelegationPrefixToAccount(ToyAccount account) {
return DELEGATION_PREFIX + account.getAddress().toHexString().substring(2);
}
public static String addDelegationPrefixToAddress(Address address) {
return DELEGATION_PREFIX + address.toHexString().substring(2);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
package net.consensys.linea.zktracer.instructionprocessing.callTests;

import net.consensys.linea.reporting.TracerTestBase;
import net.consensys.linea.testing.ToyAccount;
import net.consensys.linea.testing.ToyExecutionEnvironmentV2;
import net.consensys.linea.testing.ToyTransaction;
import org.apache.tuweni.bytes.Bytes;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;

import java.util.List;

import static net.consensys.linea.zktracer.Utils.*;

/*

CALL DELEGATION TEST

We test code delegation to different types of targets
(1) TARGET is a Smart Contract
CALL
--------> - EOA
|---------------> Smart Contract
(delegated to)
(2) TARGET is an EOA delegated to another EOA
CALL
--------> - EOA1
|---------------> EOA2
(delegated to)
(3) TARGET is an EOA delegated to itself
CALL
--------> - EOA <---------|
|-------------|
(delegated to)
(4) TARGET is an EOA delegated to another EOA delegated to a Smart Contract
CALL
--------> - EOA1
|---------------> EOA2
(delegated to) |---------------> Smart Contract
(delegated to)
(5) TARGET is a precompile
CALL
--------> - EOA
|---------------> PRC, here P256_VERIFY
(delegated to)
*/

// TODO: reenable once 7702 feature is merged
@Disabled
public class CallDelegation extends TracerTestBase {

/* Smart contract byte code
ADDRESS
SELFBALANCE
CODESIZE
CALLER
CALLVALUE
GAS
*/

final String smcBytecode = "0x30473833345a";
final ToyAccount smcAccount =
ToyAccount.builder()
.address(Address.fromHexString("1234"))
.nonce(90)
.code(
Bytes.concatenate(Bytes.fromHexString(smcBytecode)))
.build();
final String delegationCodeToSmc = addDelegationPrefixToAccount(smcAccount);

// Sender account setting
final KeyPair keyPair = new SECP256K1().generateKeyPair();
final Address senderAddress = Address.extract(Hash.hash(keyPair.getPublicKey().getEncodedBytes()));
final ToyAccount senderAccount =
ToyAccount.builder().balance(Wei.of(1_550_000_000_000L)).nonce(23).address(senderAddress).build();

/*
(1) TARGET is a Smart Contract
CALL
--------> - EOA
|---------------> Smart Contract
(delegated to)
*/
@Test
void EOADelegatedToSmc(TestInfo testInfo) {

ToyAccount eoaDelegatedToSmc =
ToyAccount.builder()
.address(Address.fromHexString("ca11ee")) // identity caller
.nonce(99)
.code(
Bytes.concatenate(Bytes.fromHexString(delegationCodeToSmc)))
.build();

Transaction tx = ToyTransaction.builder()
.sender(senderAccount)
.keyPair(keyPair)
.to(eoaDelegatedToSmc).build();

ToyExecutionEnvironmentV2.builder(chainConfig, testInfo)
.accounts(List.of(senderAccount, smcAccount, eoaDelegatedToSmc ))
.transaction(tx)
.build()
.run();
}

/*
(2) TARGET is an EOA delegated to another EOA
CALL
--------> - EOA1
|---------------> EOA2
(delegated to)
*/
@Test
void EOA1DelegatedEOA2(TestInfo testInfo) {

ToyAccount eoa2 =
ToyAccount.builder()
.address(Address.fromHexString("ca11ee2")) // identity caller
.nonce(80)
.build();

String delegationCodeToEoa2 = addDelegationPrefixToAccount(eoa2);

ToyAccount eoa1DelegatedToEoa2 =
ToyAccount.builder()
.address(Address.fromHexString("ca11ee1")) // identity caller
.nonce(99)
.code(
Bytes.concatenate(Bytes.fromHexString(delegationCodeToEoa2)))
.build();

Transaction tx = ToyTransaction.builder()
.sender(senderAccount)
.keyPair(keyPair)
.to(eoa1DelegatedToEoa2).build();

ToyExecutionEnvironmentV2.builder(chainConfig, testInfo)
.accounts(List.of(senderAccount, eoa1DelegatedToEoa2, eoa2))
.transaction(tx)
.build()
.run();
}

/*
(3) TARGET is an EOA delegated to itself
CALL
--------> - EOA <---------|
|-------------|
(delegated to)
*/
@Test
void EOADelegatedToItself(TestInfo testInfo) {

Address eoaAddress = Address.fromHexString("ca11ee1");

String delegationCodeToEoa = addDelegationPrefixToAddress(eoaAddress);

ToyAccount eoa =
ToyAccount.builder()
.address(Address.fromHexString("ca11ee1")) // identity caller
.nonce(99)
.code(
Bytes.concatenate(Bytes.fromHexString(delegationCodeToEoa)))
.build();

Transaction tx = ToyTransaction.builder()
.sender(senderAccount)
.keyPair(keyPair)
.to(eoa).build();

ToyExecutionEnvironmentV2.builder(chainConfig, testInfo)
.accounts(List.of(senderAccount, eoa))
.transaction(tx)
.build()
.run();
}

/*
(4) TARGET is an EOA delegated to another EOA
CALL
--------> - EOA1
|---------------> EOA2
(delegated to) |---------------> Smart Contract
(delegated to)
*/
@Test
void EOA1DelegatedEOA2DelegatedToSmc(TestInfo testInfo) {

ToyAccount eoa2DelegatedToSmc =
ToyAccount.builder()
.address(Address.fromHexString("ca11ee2")) // identity caller
.nonce(80)
.code(
Bytes.concatenate(Bytes.fromHexString(delegationCodeToSmc)))
.build();

String delegationCodeToEoa2 = addDelegationPrefixToAccount(eoa2DelegatedToSmc);

ToyAccount eoa1DelegatedToEoa2 =
ToyAccount.builder()
.address(Address.fromHexString("ca11ee1")) // identity caller
.nonce(99)
.code(
Bytes.concatenate(Bytes.fromHexString(delegationCodeToEoa2)))
.build();

Transaction tx = ToyTransaction.builder()
.sender(senderAccount)
.keyPair(keyPair)
.to(eoa1DelegatedToEoa2).build();

ToyExecutionEnvironmentV2.builder(chainConfig, testInfo)
.accounts(List.of(senderAccount, smcAccount, eoa1DelegatedToEoa2, eoa2DelegatedToSmc))
.transaction(tx)
.build()
.run();
}

/*
(5) TARGET is a precompile
CALL
--------> - EOA
|---------------> PRC, here P256_VERIFY
(delegated to)
*/
@Test
void targetIsPrc(TestInfo testInfo) {

String delegationCodeToP256Verify = addDelegationPrefixToAddress(Address.P256_VERIFY);
ToyAccount eoaDelegatedToPrc =
ToyAccount.builder()
.address(Address.fromHexString("ca11ee")) // identity caller
.nonce(99)
.code(
Bytes.concatenate(Bytes.fromHexString(delegationCodeToP256Verify)))
.build();

Transaction tx = ToyTransaction.builder()
.sender(senderAccount)
.keyPair(keyPair)
.to(eoaDelegatedToPrc).build();

ToyExecutionEnvironmentV2.builder(chainConfig, testInfo)
.accounts(List.of(senderAccount, eoaDelegatedToPrc))
.transaction(tx)
.build()
.run();
}

}
Loading