Skip to content

Commit

Permalink
🚧 evm: upgradableProxy üretici ekle
Browse files Browse the repository at this point in the history
  • Loading branch information
KimlikDAO-bot committed May 4, 2024
1 parent e95ff47 commit e2ee04e
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 49 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.vscode
/build
bun*
node_modules*
60 changes: 14 additions & 46 deletions ethereum/evm/builder.js → ethereum/evm/batchSend.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,16 @@
import { hexten } from "../../util/çevir";
import { Op, OpData, pushNumber } from "./opcodes";
import { Op, pushNumber } from "./opcodes";
import { evm, opsToBytes } from "./types";

/** @typedef {string} */
const Address = {};
/** @typedef {!Uint8Array} */
const ByteCode = {};
/** @type {{ addr: Address, kpass: boolean }} */
/** @type {{ addr: evm.address, kpass: boolean }} */
const AddressWithKPass = {};

/** @const {number} */
const MILLION = 1_000_000;

/** @const {!bigint} */
const SZABO = 10n ** 12n;

/**
* @param {Address} addr
* @return {OpData}
*/
const address = (addr) => {
if (addr.startsWith("0x")) addr = addr.slice(2);
return addr.toUpperCase();
}

/**
* @param {!Array<Op|OpData>} ops
* @return {ByteCode}
*/
const toByteCode = (ops) => hexten(ops.join(""));

/**
* @param {!Array<Address>} addresses
* @param {!Array<evm.address>} recipients
* @param {number} amountSzabos
* @return {ByteCode}
* @return {evm.bytes}
*/
const batchSendFixedAmount = (recipients, amountSzabos) => {
/** @const {!Array<Op|OpData>} */
Expand All @@ -41,16 +19,16 @@ const batchSendFixedAmount = (recipients, amountSzabos) => {
for (const recipient of recipients)
ops.push(Op.PUSH0, Op.PUSH0, Op.PUSH0, Op.PUSH0, Op.DUP5,
Op.PUSH20, address(recipient), Op.PUSH0, Op.CALL, Op.POP);
return toByteCode(ops.slice(0, -1));
return opsToBytes(ops.slice(0, -1));
}

/**
* Generates a batchSend bytecode for an EVM chain that doesn't support
* the PUSH0 opcode.
*
* @param {!Array<Address>} recipients
* @param {!Array<evm.address>} recipients
* @param {number} amountSzabos
* @return {ByteCode}
* @return {evm.bytes}
*/
const batchSendFixedAmountNoPush0 = (recipients, amountSzabos) => {
/** @const {!Array<Op|OpData>} */
Expand All @@ -62,7 +40,7 @@ const batchSendFixedAmountNoPush0 = (recipients, amountSzabos) => {
for (const recipient of recipients)
ops.push(Op.DUP1, Op.DUP1, Op.DUP1, Op.DUP1, Op.DUP6,
Op.PUSH20, address(recipient), Op.DUP3, Op.CALL, Op.POP);
return toByteCode(ops.slice(0, -1));
return opsToBytes(ops.slice(0, -1));
}

/**
Expand All @@ -72,7 +50,7 @@ const batchSendFixedAmountNoPush0 = (recipients, amountSzabos) => {
* @param {!Array<AddressAndKPass>} recipients
* @param {number} withKPassSzabos
* @param {number} withoutKPassSzabos
* @return {{ code: ByteCode, valueSzabos: number}}
* @return {{ code: evm.bytes, valueSzabos: number}}
*/
const batchSendWithKPassNoPush0 = (recipients, withKPassSzabos, withoutKPasstSzabos) => {
/** @const {!Array<Op|OpData>} */
Expand All @@ -90,26 +68,16 @@ const batchSendWithKPassNoPush0 = (recipients, withKPassSzabos, withoutKPasstSza
valueSzabos += kpass ? withKPassSzabos : withoutKPasstSzabos;
}
return {
code: toByteCode(ops.slice(0, -1)),
code: opsToBytes(ops.slice(0, -1)),
valueSzabos
};
}

/**
* @param {!Array<Address>} recipients
* @param {Address} token
* @param {number} amount
*/
const batchSendERC20 = (recipients, token, amountSzabos) => {

}

export {
Address,
AddressWithKPass,
ByteCode,
SZABO, batchSendERC20, batchSendFixedAmount,
SZABO,
batchSendFixedAmount,
batchSendFixedAmountNoPush0,
batchSendWithKPassNoPush0, toByteCode
batchSendWithKPassNoPush0,
};

4 changes: 2 additions & 2 deletions ethereum/evm/examples/batchSend.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { hex } from "@kimlikdao/lib/util/çevir";
import { JsonRpcProvider, Wallet } from "ethers";
import { ByteCode, SZABO, batchSendFixedAmountNoPush0 } from "../builder";
import { SZABO, batchSendFixedAmountNoPush0 } from "../builder";

/**
* @const
Expand All @@ -20,7 +20,7 @@ const batchSend = batchSendFixedAmountNoPush0([
], 100);

/**
* @param {!ByteCode} program
* @param {evm.bytes} program
*/
const send = async (program) => {
/**
Expand Down
14 changes: 13 additions & 1 deletion ethereum/evm/opcodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@ const Op = {
ADD: "01",
SHA3: "20",
CALLDATASIZE: "36",
CALLDATACOPY: "37",
CODECOPY: "39", // destOffset, offset, length, memory[destOffset:destOffset+length] = code[offset:offset+length]
RETURNDATASIZE: "3D",
RETURNDATACOPY: "3E",
DIFFICULTY: "44",
GASLIMIT: "45",
CHAINID: "46",
POP: "50",
MSTORE: "52",
SLOAD: "54",
SSTORE: "55",
JUMP: "56",
JUMPI: "57",
GAS: "5A",
JUMPDEST: "5B",
PUSH0: "5F",
PUSH1: "60",
PUSH20: "73",
Expand All @@ -23,7 +32,9 @@ const Op = {
DUP16: "8F",
CREATE: "FO", // CREATE(value, offset, length)
CALL: "F1", // CALL(gas, addr, value, argsOffset, argsLength, retOffset, retLength)
RETURN: "F3" // RETURN(offset, length) return memory[offset : offset + length]
RETURN: "F3", // RETURN(offset, length) return memory[offset : offset + length]
DELEGATECALL: "F4", // DELEGATECALL(gas, addr, argsOffset, argsLength, retOffset, retLength)
REVERT: "FD"
}

/**
Expand All @@ -48,6 +59,7 @@ const pushN = (n) => /** @type {Op} */((95 + n).toString(16));
* @return {!Array<Op|OpData>}
*/
const pushNumber = (n) => {
if (n == 0) return [Op.PUSH0];
/** @type {string} */
let ser = n.toString(16);
if (ser.length & 1) ser = "0" + ser;
Expand Down
57 changes: 57 additions & 0 deletions ethereum/evm/proxies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Op, pushNumber } from "./opcodes";
import { address, concat, evm, opsToBytes } from "./types.js";

/**
* @param {number} offset
*/
const delegateCall = (offset) => opsToBytes([
Op.CALLDATASIZE,
Op.PUSH0,
Op.PUSH0,
Op.CALLDATACOPY,
Op.PUSH0,
Op.PUSH0,
Op.CALLDATASIZE,
Op.PUSH0,
Op.PUSH0,
Op.SLOAD,
Op.GAS,
Op.DELEGATECALL,
Op.RETURNDATASIZE,
Op.PUSH0,
Op.PUSH0,
Op.RETURNDATACOPY,
Op.RETURNDATASIZE,
Op.PUSH0,
Op.DUP3,
...pushNumber(offset + 23),
Op.JUMPI,
Op.REVERT,
Op.JUMPDEST,
Op.RETURN
]);

/**
* @param {evm.address} codeAddress
* @return {evm.bytes}
*/
const upgradableProxy = (codeAddress) => {
/** @const {evm.bytes} */
const dc = delegateCall(0);

return concat(opsToBytes([
Op.PUSH20, address(codeAddress), Op.PUSH0, Op.SSTORE, // storage[0] = codeAddress
...pushNumber(dc.length),
Op.DUP1, // len len
...pushNumber(32), // 32 len len
Op.PUSH0, // 0 32 len len
Op.CODECOPY, // len
Op.PUSH0, // 0 len
Op.RETURN
]), dc);
}

export {
delegateCall,
upgradableProxy
};
17 changes: 17 additions & 0 deletions ethereum/evm/test/proxies.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { describe, expect, test } from "bun:test";
import vm from "../../../testing/vm";
import { hex } from "../../../util/çevir";
import { Op } from "../opcodes";
import { delegateCall, upgradableProxy } from "../proxies";

describe("", () => {
test("", () => {
const dc = delegateCall(0);
expect(dc[dc[dc.length - 5]]).toBe(parseInt(Op.JUMPDEST, 16));
});

test("output", async () => {
const up = upgradableProxy(vm.addr(1));
console.log(hex(up.subarray(32)))
})
})
44 changes: 44 additions & 0 deletions ethereum/evm/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { hexten } from "../../util/çevir";

/** @const */
const evm = {};

/** @typedef {string} */
evm.address = {};

/** @typedef {!Uint8Array} */
evm.bytes = {};

/**
* @param {!Array<!Op|!OpCode>} ops
* @return {evm.bytes}
*/
const opsToBytes = (ops) => hexten(ops.join(""));

/**
* @param {evm.bytes} b1
* @param {evm.bytes} b2
* @return {evm.bytes}
*/
const concat = (b1, b2) => {
const ret = new Uint8Array(b1.length + b2.length);
ret.set(b1);
ret.set(b2, b1.length);
return ret;
}

/**
* @param {Address} addr
* @return {OpData}
*/
const address = (addr) => {
if (addr.startsWith("0x")) addr = addr.slice(2);
return addr.toUpperCase();
}

export {
evm,
address,
concat,
opsToBytes
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"test": "bun test"
},
"devDependencies": {
"@ethereumjs/evm": "^3.0.0",
"@noble/secp256k1": "^2.0.0",
"ethers": "^6.10.0",
"google-closure-compiler": "^20230802.0.0",
Expand Down

0 comments on commit e2ee04e

Please sign in to comment.