Skip to content

Commit

Permalink
Add ability for ArtifactManager to identify contracts without metadat…
Browse files Browse the repository at this point in the history
…a hash; Add tests for contract liftime transformer
  • Loading branch information
cd1m0 committed Oct 6, 2024
1 parent 14125cd commit 36ee954
Show file tree
Hide file tree
Showing 8 changed files with 5,530 additions and 0 deletions.
415 changes: 415 additions & 0 deletions src/debug/artifact_manager/artifact_manager.ts

Large diffs are not rendered by default.

65 changes: 65 additions & 0 deletions src/debug/artifact_manager/bytecode_templates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { equalsBytes, hexToBytes } from "@ethereumjs/util";
import { PartialBytecodeDescription, RangeList } from "../../artifacts";

Check failure on line 2 in src/debug/artifact_manager/bytecode_templates.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Module '"../../artifacts"' has no exported member 'RangeList'.

export interface BytecodeTemplate {
object: Uint8Array;
skipRanges: Array<[number, number]>;
}

function makeSkipRanges(rawList: RangeList): Array<[number, number]> {
return rawList.map((raw) => [raw.start, raw.start + raw.length]);

Check failure on line 10 in src/debug/artifact_manager/bytecode_templates.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Parameter 'raw' implicitly has an 'any' type.
}

export function makeTemplate(artifact: PartialBytecodeDescription): BytecodeTemplate {
const skipRanges: Array<[number, number]> = [];

if (artifact.linkReferences) {

Check failure on line 16 in src/debug/artifact_manager/bytecode_templates.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Property 'linkReferences' does not exist on type 'PartialBytecodeDescription'.
for (const obj of Object.values(artifact.linkReferences)) {

Check failure on line 17 in src/debug/artifact_manager/bytecode_templates.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Property 'linkReferences' does not exist on type 'PartialBytecodeDescription'.
for (const ranges of Object.values(obj)) {

Check failure on line 18 in src/debug/artifact_manager/bytecode_templates.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

No overload matches this call.
skipRanges.push(...makeSkipRanges(ranges));
}
}
}

if (artifact.immutableReferences) {

Check failure on line 24 in src/debug/artifact_manager/bytecode_templates.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Property 'immutableReferences' does not exist on type 'PartialBytecodeDescription'.
for (const ranges of Object.values(artifact.immutableReferences)) {

Check failure on line 25 in src/debug/artifact_manager/bytecode_templates.ts

View workflow job for this annotation

GitHub Actions / build (20.x)

Property 'immutableReferences' does not exist on type 'PartialBytecodeDescription'.
skipRanges.push(...makeSkipRanges(ranges));
}
}

skipRanges.sort();

return {
object: hexToBytes("0x" + artifact.object),
skipRanges
};
}

export function matchesTemplate(bytecode: Uint8Array, template: BytecodeTemplate): boolean {
if (bytecode.length !== template.object.length) {
return false;
}

let curIdx = 0;
let rangeIdx = 0;

while (curIdx < template.object.length) {
let nextIdx: number;
let compEnd: number;

if (rangeIdx < template.skipRanges.length) {
[compEnd, nextIdx] = template.skipRanges[rangeIdx];
} else {
compEnd = nextIdx = template.object.length;
}

if (!equalsBytes(bytecode.slice(curIdx, compEnd), template.object.slice(curIdx, compEnd))) {
return false;
}

curIdx = nextIdx;
rangeIdx++;
}

return true;
}
1 change: 1 addition & 0 deletions src/debug/artifact_manager/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./artifact_manager";
4,748 changes: 4,748 additions & 0 deletions test/samples/local/contract_lifetime/artifacts/main.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
pragma solidity 0.8.21;

contract FailingConstructor {
constructor() public {
revert();
}
}

contract Killable {
function die() public {
selfdestruct(payable(0x0));
}
}

contract NestedCreation is Killable {
Killable k;
constructor() public {
k = new Killable();
}
}

contract NestedCreationFail is Killable {
constructor() public {
try new FailingConstructor() returns (FailingConstructor k) {} catch {
// nada
}
Killable k = new Killable();
}
}
12 changes: 12 additions & 0 deletions test/samples/local/contract_lifetime/contracts/hardhat.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require("@nomicfoundation/hardhat-ethers");
/**
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "0.8.21",
networks: {
localhost: {
url: "http://localhost:7545"
}
}
};
40 changes: 40 additions & 0 deletions test/samples/local/contract_lifetime/contracts/mktx.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ethers } from "hardhat";

(async function main() {
const FailingConstructor = await ethers.getContractFactory("FailingConstructor");

const tx = await FailingConstructor.getDeployTransaction();
console.error("FailingConstructor bytecode:", tx.data);

// Failing constructor
try {
const t = await FailingConstructor.deploy();
await t.wait();
} catch (e) {
console.error(`Failed as expected`);
}

// Working constructor
const Killable = await ethers.getContractFactory("Killable");
const killable = await Killable.deploy();

console.error("Killable bytecode:", await Killable.getDeployTransaction());
console.error(`Deployed Killable at `, await killable.getAddress());

// Self-destruct
const t = await killable.die();
console.error(`Die tx: `, t);

// Nested creation
const NestedCreation = await ethers.getContractFactory("NestedCreation");
const nestedCreation = await NestedCreation.deploy();

console.error("NestedCreation bytecode:", await NestedCreation.getDeployTransaction());
console.error(`Deployed nested creation at `, await nestedCreation.getAddress());
// Nested creation with failure
const NestedCreationFail = await ethers.getContractFactory("NestedCreationFail");
const nestedCreationFail = await NestedCreationFail.deploy();

console.error("NestedCreationFail bytecode:", await NestedCreationFail.getDeployTransaction());
console.error(`Deployed nested creation fail at `, await nestedCreationFail.getAddress());
})();
220 changes: 220 additions & 0 deletions test/samples/local/contract_lifetime/txs/tx00.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
{
"initialState": {
"accounts": {
"0xAaaaAaAAaaaAAaAAaAaaaaAAAAAaAaaaAaAaaAA0": {
"nonce": 0,
"balance": "0x0000000000000000000000f000000000",
"code": "",
"storage": {}
},
"0xAaAaaAAAaAaaAaAaAaaAAaAaAAAAAaAAAaaAaAa2": {
"nonce": 0,
"balance": "0x0000000000000000000000f000000000",
"code": "",
"storage": {}
},
"0xafFEaFFEAFfeAfFEAffeaFfEAfFEaffeafFeAFfE": {
"nonce": 0,
"balance": "0x0000000000000000000000f000000000",
"code": "",
"storage": {}
}
}
},
"steps": [
{
"address": "0x0000000000000000000000000000000000000000",
"gasLimit": "0xff0000",
"gasPrice": "0x1",
"input": "0x6080604052348015600e575f80fd5b5f80fdfe",
"origin": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"value": "0x0",
"blockCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"blockDifficulty": "0xc",
"blockGasLimit": "0xff0000",
"blockNumber": 1,
"blockTime": 1,
"result": {
"kind": "revert"
},
"liveContracts": []
},
{
"address": "0x0000000000000000000000000000000000000000",
"gasLimit": "0xff0000",
"gasPrice": "0x1",
"input": "0x6080604052348015600e575f80fd5b5060818061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c806335f4699414602a575b5f80fd5b60306032565b005b5f73ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220aac49067c690fc4a7a711ec18c9a8b6accf3004cea6deef0a7f51a029997a97e64736f6c63430008150033",
"origin": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"value": "0x0",
"blockCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"blockDifficulty": "0xc",
"blockGasLimit": "0xff0000",
"blockNumber": 1,
"blockTime": 1,
"result": {
"kind": "contract_created",
"address": "0x1faca6f2f8e169c54e0b1fe6d889dfc21ab5737e"
},
"liveContracts": []
},
{
"address": "0x1faca6f2f8e169c54e0b1fe6d889dfc21ab5737e",
"gasLimit": "0xff0000",
"gasPrice": "0x1",
"input": "0x35f46994",
"origin": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"value": "0x0",
"blockCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"blockDifficulty": "0xc",
"blockGasLimit": "0xff0000",
"blockNumber": 2,
"blockTime": 2,
"result": {
"kind": "value_returned",
"value": ""
},
"liveContracts": ["0x1faca6f2f8e169c54e0b1fe6d889dfc21ab5737e"]
},
{
"address": "0x0000000000000000000000000000000000000000",
"gasLimit": "0xff0000",
"gasPrice": "0x1",
"input": "0x608060405234801561000f575f80fd5b5060405161001c90610079565b604051809103905ff080158015610035573d5f803e3d5ffd5b505f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610085565b609c8061011283390190565b6081806100915f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c806335f4699414602a575b5f80fd5b60306032565b005b5f73ffffffffffffffffffffffffffffffffffffffff16fffea264697066735822122022b5ad5f782b0bc41d4425d4f3537930800b64da0c6d3808b7c1cfc35533989364736f6c634300081500336080604052348015600e575f80fd5b5060818061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c806335f4699414602a575b5f80fd5b60306032565b005b5f73ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220aac49067c690fc4a7a711ec18c9a8b6accf3004cea6deef0a7f51a029997a97e64736f6c63430008150033",
"origin": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"value": "0x0",
"blockCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"blockDifficulty": "0xc",
"blockGasLimit": "0xff0000",
"blockNumber": 1,
"blockTime": 1,
"result": {
"kind": "contract_created",
"address": "0x66d9baa1e8afa844766e15103b3b2a533304af5b"
},
"liveContracts": []
},
{
"address": "0x0000000000000000000000000000000000000000",
"gasLimit": "0xff0000",
"gasPrice": "0x1",
"input": "0x608060405234801561000f575f80fd5b5060405161001c90610064565b604051809103905ff0801561002e5760015b1561003557505b5f60405161004290610070565b604051809103905ff08015801561005b573d5f803e3d5ffd5b5090505061007c565b60138061010983390190565b609c8061011c83390190565b6081806100885f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c806335f4699414602a575b5f80fd5b60306032565b005b5f73ffffffffffffffffffffffffffffffffffffffff16fffea264697066735822122005e088379ce3c7f9582da2f32848f32e2a0e0351d10b82981d122e2f0ac9963664736f6c634300081500336080604052348015600e575f80fd5b5f80fdfe6080604052348015600e575f80fd5b5060818061001b5f395ff3fe6080604052348015600e575f80fd5b50600436106026575f3560e01c806335f4699414602a575b5f80fd5b60306032565b005b5f73ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220aac49067c690fc4a7a711ec18c9a8b6accf3004cea6deef0a7f51a029997a97e64736f6c63430008150033",
"origin": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"value": "0x0",
"blockCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"blockDifficulty": "0xc",
"blockGasLimit": "0xff0000",
"blockNumber": 1,
"blockTime": 1,
"result": {
"kind": "contract_created",
"address": "0x8d57cb6b2c9889b43514e729b70c17d7afb8227c"
},
"liveContracts": [
"0x66d9baa1e8afa844766e15103b3b2a533304af5b",
"0x5706659cf82b70d4b805ba2e9540cbc1b60fec22"
]
},
{
"address": "0x8d57cb6b2c9889b43514e729b70c17d7afb8227c",
"gasLimit": "0xff0000",
"gasPrice": "0x1",
"input": "0x35f46994",
"origin": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"value": "0x0",
"blockCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"blockDifficulty": "0xc",
"blockGasLimit": "0xff0000",
"blockNumber": 2,
"blockTime": 2,
"result": {
"kind": "value_returned",
"value": ""
},
"liveContracts": [
"0x5706659cf82b70d4b805ba2e9540cbc1b60fec22",
"0x66d9baa1e8afa844766e15103b3b2a533304af5b",
"0x8d57cb6b2c9889b43514e729b70c17d7afb8227c",
"0x99ef7cc5214b804f7ffba13c70a2d7c2f9763d60"
]
},
{
"address": "0x5706659cf82b70d4b805ba2e9540cbc1b60fec22",
"gasLimit": "0xff0000",
"gasPrice": "0x1",
"input": "0x35f46994",
"origin": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"value": "0x0",
"blockCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"blockDifficulty": "0xc",
"blockGasLimit": "0xff0000",
"blockNumber": 2,
"blockTime": 2,
"result": {
"kind": "value_returned",
"value": ""
},
"liveContracts": [
"0x5706659cf82b70d4b805ba2e9540cbc1b60fec22",
"0x66d9baa1e8afa844766e15103b3b2a533304af5b",
"0x99ef7cc5214b804f7ffba13c70a2d7c2f9763d60"
]
},
{
"address": "0x66d9baa1e8afa844766e15103b3b2a533304af5b",
"gasLimit": "0xff0000",
"gasPrice": "0x1",
"input": "0x35f46994",
"origin": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"value": "0x0",
"blockCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"blockDifficulty": "0xc",
"blockGasLimit": "0xff0000",
"blockNumber": 2,
"blockTime": 2,
"result": {
"kind": "value_returned",
"value": ""
},
"liveContracts": [
"0x66d9baa1e8afa844766e15103b3b2a533304af5b",
"0x99ef7cc5214b804f7ffba13c70a2d7c2f9763d60"
]
},
{
"address": "0x99ef7cc5214b804f7ffba13c70a2d7c2f9763d60",
"gasLimit": "0xff0000",
"gasPrice": "0x1",
"input": "0x35f46994",
"origin": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"value": "0x0",
"blockCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"blockDifficulty": "0xc",
"blockGasLimit": "0xff0000",
"blockNumber": 2,
"blockTime": 2,
"result": {
"kind": "value_returned",
"value": ""
},
"liveContracts": ["0x99ef7cc5214b804f7ffba13c70a2d7c2f9763d60"]
},
{
"address": "0x99ef7cc5214b804f7ffba13c70a2d7c2f9763d60",
"gasLimit": "0xff0000",
"gasPrice": "0x1",
"input": "0x35f46994",
"origin": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"value": "0x0",
"blockCoinbase": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0",
"blockDifficulty": "0xc",
"blockGasLimit": "0xff0000",
"blockNumber": 2,
"blockTime": 2,
"result": {
"kind": "value_returned",
"value": ""
},
"liveContracts": []
}
]
}

0 comments on commit 36ee954

Please sign in to comment.