loom_execution_multicaller/
opcodes_encoder.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use std::ops::{BitOrAssign, Shl};

use alloy_primitives::{Bytes, U256};
use alloy_sol_types::SolInterface;
use eyre::{ErrReport, Result};
use lazy_static::lazy_static;

use loom_defi_abi::multicaller::IMultiCaller;
use loom_types_blockchain::{CallType, MulticallerCall, MulticallerCalls};

lazy_static! {
    static ref VALUE_CALL_SELECTOR: U256 = U256::from(0x7FFA);
    static ref CALCULATION_CALL_SELECTOR: U256 = U256::from(0x7FFB);
    static ref ZERO_VALUE_CALL_SELECTOR: U256 = U256::from(0x7FFC);
    static ref INTERNAL_CALL_SELECTOR: U256 = U256::from(0x7FFD);
    static ref STATIC_CALL_SELECTOR: U256 = U256::from(0x7FFE);
    static ref DELEGATE_CALL_SELECTOR: U256 = U256::from(0x7FFF);
}

pub struct OpcodesEncoderV2;

pub trait OpcodesEncoder {
    fn pack_do_calls(opcodes: &MulticallerCalls) -> Result<Bytes>;
    fn pack_do_calls_data(opcode: &MulticallerCalls) -> Result<Bytes>;
}

impl OpcodesEncoderV2 {
    fn pack_opcode(opcode: &MulticallerCall) -> Result<Vec<u8>> {
        let mut ret: Vec<u8> = Vec::new();
        let mut selector = U256::ZERO;
        //let mut selector_bytes_len = 0x20;
        let selector_call = match opcode.call_type {
            CallType::Call => {
                if opcode.value.is_none() {
                    *ZERO_VALUE_CALL_SELECTOR
                } else {
                    *VALUE_CALL_SELECTOR
                }
            }
            CallType::DelegateCall => *DELEGATE_CALL_SELECTOR,
            CallType::InternalCall => {
                //selector_bytes_len = 0xC;
                *INTERNAL_CALL_SELECTOR
            }
            CallType::StaticCall => *STATIC_CALL_SELECTOR,
            CallType::CalculationCall => {
                //selector_bytes_len = 0xC;
                *CALCULATION_CALL_SELECTOR
            }
            _ => {
                return Err(ErrReport::msg("WRONG_OPCODE"));
            }
        };

        if selector_call == *VALUE_CALL_SELECTOR && !opcode.value.unwrap_or_default().is_zero() {
            selector = opcode.value.unwrap_or_default().shl(0x10);
            selector.bitor_assign(U256::from(1).shl(96 - 1));
            selector.bitor_assign(U256::from(opcode.call_data.len()).shl(0));
        } else {
            selector.bitor_assign(selector_call.shl(80));
            selector.bitor_assign(U256::from(opcode.call_data.len()).shl(0));
            selector.bitor_assign(U256::from(opcode.call_stack & 0xFFFFFF).shl(16));
            selector.bitor_assign(U256::from(opcode.return_stack & 0xFFFFFF).shl(40));
        }

        let selector_bytes = selector.to_be_bytes::<32>();
        ret.append(&mut selector_bytes[20..32].to_vec());

        match opcode.call_type {
            CallType::CalculationCall | CallType::InternalCall => {}
            _ => {
                let mut address_bytes = opcode.to.to_vec();
                ret.append(&mut address_bytes);
            }
        }

        ret.append(&mut opcode.call_data.to_vec());

        Ok(ret)
    }
}

impl OpcodesEncoder for OpcodesEncoderV2 {
    fn pack_do_calls(opcodes: &MulticallerCalls) -> Result<Bytes> {
        let call_data = OpcodesEncoderV2::pack_do_calls_data(opcodes)?;
        let args = IMultiCaller::doCallsCall { data: call_data };
        let call = IMultiCaller::IMultiCallerCalls::doCalls(args);
        Ok(call.abi_encode().into())
    }

    fn pack_do_calls_data(opcodes: &MulticallerCalls) -> Result<Bytes> {
        let mut call_data: Vec<u8> = Vec::new();
        for o in opcodes.opcodes_vec.iter() {
            call_data.append(&mut OpcodesEncoderV2::pack_opcode(o)?);
        }
        Ok(call_data.into())
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test() {
        let buf = Bytes::from(vec![0x33, 0x33, 0x44, 0x55]);

        let mut opcode = MulticallerCall::new_internal_call(&buf);
        //let mut opcode = Opcode::new_internal_call(to, &Some(buf));
        opcode.set_call_stack(true, 0, 24, 0x20).set_return_stack(true, 1, 44, 0x20);

        let mut opcodes = MulticallerCalls::new();
        opcodes.add(opcode);

        let packed_bytes = OpcodesEncoderV2::pack_do_calls(&opcodes).unwrap();
        println!("{:?}", packed_bytes);
    }
}